Utilisateur:Daahbot/scripts/format.py

# -*- coding: utf-8  -*-
#
# (C) Daniel Herding, 2004
#
# Distributed under the terms of the MIT license.
#
####################################################################################
#
# Version pas mal modifiée pour formater les articles du Wiktionnaire fr
# BUT PRINCIPAL : ranger les sections des articles dans l'ordre conventionnel
# Peut être éventuellement utilisé pour formater une section ciblée
# (par exemple : seulement l'étymologie, seulement les traductions, etc.)
#
####################################################################################

__version__='$Id'

from __future__ import generators
import sys, re
import wikipedia, pagegenerators, catlib, config
from liste_langues import langues

# Liste des messages
msg = {
       'fr':u'Robot : structure des articles',
       }

# Log des différences (nécessite la déf difflog de wikipedia personnalisé) :
dossier_log = u"log xml/format/"
fichierlog = dossier_log + u"log.txt"

# Attribution des clés pour les langues (dont fr, conv et car) :
c=0
cl= "0000"
langues2 ={}
for lang in langues:
    langues2[cl] = lang
    c+=1
    cl=str(c)
    if c<10: cl = "0" + cl
    if c<100: cl = "0" + cl
    if c<1000: cl = "0" + cl
clesl = langues2.keys()
clesl.sort()

#for c in clesl:
#    print c, langues2[c], u" ; ",

types_de_mot0 = ("nom", "loc-nom",
                "nom-pr",
                "adj", "loc-adj", "adj-dem", "adj-indef", "adj-num", "adj-pos",
                "adv", "loc-adv",
                "verb", "loc-verb",
                "pronom", "pronom-def", "pronom-indef", "pronom-int", "pronom-pos", "pronom-pers", "pronom-rel",
                "art", "art-def", "art-indef", "art-part",
                "conj", "loc-conj",
                "prep", "loc-prep",
                 "onoma",
                 "loc", "locution", "prov", "abr",
                 "symb", 
                 "class", 
                 "part", "post", "suf", "pref", "aff")

section_langue = (
    (u"etym", "01"),
    (u"pron", "z2" ),
    (u"voir", "z5"),
    (u"réf", "z6"),
    (u"homo", "z3"),
    (u"paro", "z4")
    )

# Pas encore utilisé car pas décidé (et il en manque quelques uns)
# Ne pas oublier de donner une clef !
# Voir format_type
section_type0 = ("ortho-alt", "syn", "ant", "hyper", "hypo", "hyper", "holo", "mero", "trad", "drv", "apr", "exp", "drv-int", "apr-int")


############################################################
#   Deux fonctions utiles de remplacement (dont regex)     #
############################################################
def my_repl(original_text, old, new):
        new_text = original_text
        try:
            new_text = old.sub(new, new_text)
        except:
            new_text = new_text.replace(old, new)
        return new_text

def my_replex(text0, old, new):
    old = re.compile(old, re.UNICODE)
    # changement :      
    new_text = old.sub(new, text0)
    return new_text


def balisage(text, titre):
################################################
#   Cette déf balise les sections d'articles   #
################################################
    
# I) BALISAGE DES SECTIONS DE LANGUES
    # A) Sections générales, langues particulières, etc.
    text = my_repl(text, u"{{-car-}}",   u"{{=:car:=}}")
    #text = my_repl(text, u"{{=conv=}}",   u"{{=:00002conv:=}}")
    #text = my_repl(text, u"{{=fr=}}",   u"{{=:00003fr:=}}")
    
    # Autres langues
    #text = my_replex(text, u"{{=([^:]+?)=}}",   r"{{=:\1:=}}")
    for lang in langues:
        text = my_repl(text, u"{{="+ lang + u"=}}",    u"{{=:"+ lang + u":=}}")


    # Les catégories aussi :
    text = my_repl(text, u"[[catégorie:",u"[[Catégorie:")
    try:
        categorie_start = re.search(u"\[\[Catégorie\:([^\]]*)\]\]", text).start()
        text = text[:categorie_start]+ u"{{=:zz3:cat:=}}" + text[categorie_start:]
        
    # Si pas de catégories :
    except:
        try:
            interwiki_start = re.search(u"\[\[...?:.+?\]\]", text).start()
            text = text[:interwiki_start]+ u"{{=:zz3:cat:=}}" + text[interwiki_start:]
        except:
            text += u"\n{{=:zz3:cat:=}}"
            print "Pas de catégorie ni d'interwikis"

    # B) BALISAGE DES SECTIONS INTRA-LANGUES
    text = my_repl(text, u"{{-etym-}}",   u"{{--:etym:--}}")
    text = my_repl(text, u"{{-pron-}}",   u"{{--:pron:--}}")
    text = my_repl(text, u"{{-homo-}}",   u"{{--:homo:--}}")
    text = my_repl(text, u"{{-paro-}}",   u"{{--:paro:--}}")
    text = my_repl(text, u"{{-voir-}}",   u"{{--:voir:--}}")
    text = my_repl(text, u"{{-réf-}}",   u"{{--:réf:--}}")

    # Attention : types numérotés !
    text = my_replex(text, u"-\|([1-9]+?)\}\}",   r"-}}___num_\1__")
    # Et types
    for typ in types_de_mot0:
        text = my_repl(text, u"{{-"+ typ + u"-}}",    u"{{--:"+ typ + u":.-}}")
    
    # C) Sections intra-type (à faire)
    
    return text

def debalisage(text, titre):
############################################################
#   Cette déf enlève les balises des sections d'articles   #
############################################################
    # Sections générales        
    text = my_repl(text, u"{{=:car:=}}", u"{{-car-}}")
    #text = my_repl(text, u"{{=:00002conv:=}}", u"{{=conv=}}")
    #text = my_repl(text, u"{{=:00003fr:=}}", u"{{=fr=}}")
    text = my_replex(text, u"{{=:([^:]+?):=}}", r"{{=\1=}}")
    # Catégories
    text = my_repl(text, u"\n{{=:zz3:cat:=}}__rien__", u"")
    text = my_repl(text, u"{{=:zz3:cat:=}}", u"")

    # Sections intra-langues
    text = my_repl(text, u"{{--:etym:--}}", u"{{-etym-}}")
    text = my_repl(text, u"{{--:ron:--}}", u"{{-pron-}}")
    text = my_repl(text, u"{{--:homo:--}}", u"{{-homo-}}")
    text = my_repl(text, u"{{--:paro:--}}", u"{{-paro-}}")
    text = my_repl(text, u"{{--:voir:--}}", u"{{-voir-}}")
    text = my_repl(text, u"{{--:réf:--}}", u"{{-réf-}}")

    # Plus celle de la fusion des types, déf format_langue
    text = my_replex(text, u"{{--:(.+?):.-}}", r"{{-\1-}}")
    text = my_replex(text, u"{{--:(.+?):--}}", r"{{-\1-}}")
    
    # Attention : types numérotés !
    text = my_replex(text,u"-}}___num_([1-9][1-9]?)__", r"-|\1}}")
    
    return text

    # C) Sections intra-type (à faire)

def format_article(text, titre):
############################################################
#   Cette déf formate la structure générale des articles   #
############################################################
    articles = {}
    catentro = {}
    itwentro = {}
    categories = u''
# Préboulot lourd : rapatrier les catégories qui trainent partout et qui font tout planter mon bot...
    text, catentro, itwentro = rapatri_cat(text)

# I) Séparation de l'article en morceaux
    parties = text.split(u"{{=:")

# Vérification de la teneur des sections séparées    
    for i, p in enumerate(parties):
        search = re.search(u":=}}", p)
        # S'il le trouve : c'est une section
        if search:
            end = search.start()
            cle = p[:end]
            article = u"{{=:" + p
            # Si cette section n'est pas une section de catégorie :
            if cle <>"zz3:cat":
                article = format_langue(article, cle, titre)

            # Vérification que c'est une langue enregistrée, et dans ce cas on lui donne sa valeur
            for clf in clesl:
                if cle == langues2[clf]:
                    cle = clf
            # Puis enregitrement
            articles[cle] = article
                
            if cle == "zz3:cat":
                categories = my_repl(article, u"{{=:zz3:cat:=}}", u"")
                # Sinon c'est le début (normalement)
        else:
            articles["0"] = p

    # Ajout à la section catégorie des éléments cat et int en trop
    articles["zz3:cat"] = format_cat(categories, titre, catentro, itwentro)
        
  
    resultat = u""
    cles = articles.keys()
    cles.sort()
    print "\nOrdre : ",
    for clf in cles:
        if clf=="0":
            print "DEBUT",
        else:
            try:
                print langues2[clf],
            except:
                print clf,
    print "\n"

    # Recommposition de l'article fragmenté ordre simple
    for c in cles:
        #print "Tri=", repr(c)
        resultat += articles[c]
    
    return resultat

def format_langue(text, lang, titre):
##################################################################
#   Cette déf formate la structure dans les sections de langue   #
##################################################################
    # Sachant que text est une section de langue bien isolée
    text = my_replex(text, "\n+", "\n")
    
    # Recherche des sous-sections
    print "\nFormatage de la partie " + lang + " : "
    parties = text.split(u"{{--:")
    articles2 = {}

    
    # Vérification de la teneur des sections séparées 
    types = u""
    for i, n in enumerate(parties):
        
        # Types de mot ?
        search2 = None
        search2 = re.search(u":\.-}}", n)
        # S'il le trouve : c'est une section de type de mot
        if search2 <> None:
            finom = search2.start()
            nom = n[:finom]
            print nom, u"est une section de type"

            ntyp = format_type(n, lang, titre)
            
            types += (u"{{--:" + ntyp)
            
        else:
            
        #Autres sections
            search3 = 0
            search3 = re.search(u":--}}", n)
        # S'il le trouve : c'est une section
            if search3 <> None:
                end2 = search3.start()
                cle2 = n[:end2]
                print cle2, u"est une section non-type, clé = ", 
                for nom, clef in section_langue:
                    if nom == cle2:
                        articles2[clef] = u"{{--:" + n
                        print clef
                        if cle2 == "pron":
                             articles2[clef] = format_pron(articles2[clef], lang, titre)
                        elif cle2 == "etym":
                             articles2[clef] = format_etym(articles2[clef], lang, titre)
                            
            
            # Sinon c'est le début (normalement)
            else:
                if n <> u"" :
                    cle2 = u"%i" % i
                    articles2[cle2] = n
                    print cle2, u" est le début de la section"
    
        
            # Ajout dans l'articles2
    articles2["02"] = types
        
    resultat2 = u""
    cles2 = articles2.keys()
    cles2.sort()
    # Donne le nouvel ordre des clés
    #print articles2.keys()

    # Recommposition de l'article fragmenté ordre simple
    for c in cles2:
        #print "Tri2=", repr(c)
        resultat2 += articles2[c]
    
    return resultat2

def format_type(text, lang, titre):
##################################################################
#  Cette déf formate la structure de la section de type de mot   #
#  beta : juste les déf pour le moment, en attendant qu'une      #
#  décision soit prise sur l'ordre des sous-sections.            #
##################################################################
    print u"  * Formatage des définitions :\n  -> ",
    text0 = text    
    
    # Format probablement à refaire à la main
    if re.search(u"\n##", text):
        chemf = open(u"log xml/format/bug.txt", "a")
        titre = u"\n" + text + u"\n"
        chemf.write(titre.encode('utf8'))
        chemf.close()
        text = my_replex(text, u"\n##", r"\n__dou__\n#")
        
    text = my_replex(text, u"\n#:", r"\n___ex___")

# Boucle pour protéger les term
    num=0
    while num<40:
        text = my_replex(text, u"\n# \{\{ébauche-déf\|(...?)\}\}", r"\n# Eb_\1__\n")
        text = my_replex(text, u"\n# ?\{\{(.+?)\}\}", r"\n___term_\1___\n# ")
        num +=1

    # S'il n'y a rien sur la ligne
    text = my_replex(text, u"\n# ?…\n", u"\n# {{ébauche-déf|" + lang + u"}}\n")
    
    # Points en fin de phrase...
    # D'abord : éviter les espaces en fin de ligne
    text = my_replex(text, u"(\n.+?) +?(\r)", r"\1\2")
    text = my_replex(text, u"(\n# [^\r^\n]+?) (\n)", r"\1\2")
    #text = my_replex(text, u"(\n# ?)(.+?)([^\.^,^:^;^…^\r^\n^'^!^?^>])\r", r"\1\2\3.\n")
    text = my_replex(text, u"(\n# ?)(.+?[^\.^,^:^;^…^\r^\n^'^!^?^>^\}]) ?\n", r"\1\2.\n")
    text = my_replex(text, u"(\n# ?)(.+?[^\.^,^:^;^…^\r^\n^'^!^?^>^\}]) ?\n", r"\1\2.\n")

    # Majuscule en début de phrase...
    text = my_replex(text, u"(\n# ?)\[\[([^\|^A-Z]+?)\]\]", r"\1[[\2|{{subst:UCFIRST:\2}}]]")
    text = my_replex(text, u"(\n# ?)'''([^'^A-Z]+?)'''", r"\1'''{{subst:UCFIRST:\2}}'''")
    text = my_replex(text, u"(\n# ?)([^ ^\[^\{^A-Z^'^(])", r"\1{{subst:UC:\2}}")


# Boucle pour déprotéger les term
    num=0
    while num<40:
        text = my_replex(text, u"\n# Eb_(...?)__\.?\n", u"\n# {{ébauche-déf|" + r"\1}}\n",)
        text = my_replex(text, u"___term_(.+?)___\.?\n# ", r"# {{\1}}")
        num +=1
    text = my_replex(text, u"___ex___", r"#:")
    text = my_replex(text, u"\n__dou__\n#", r"\n##")

    if text0 == text:
        print "aucun changement"
    else:
        print u"changements effectués"
        
    return text

def format_etym(text, lang, titre):
############################################################
#   pour formater la typo de la section d'étymologie       #
#   * format des lignes (ajout point en fin de phrase      #
#   * Ajout d'ébauche                                      #
############################################################
    print u"  * Formatage de l'étymologie :\n  -> ",
    text0 = text
    
    text = my_replex(text, u"(etym:--\}\})\r\n: ?…?\r\n", r"\1" + u"\n: {{ébauche-étym|" + lang + "}}\n")
    text = my_replex(text, u"(etym:--\}\})\n: ?…?\n", r"\1" + u"\n: {{ébauche-étym|" + lang + "}}\n")
    
    # Points en fin de phrase...
    # D'abord : éviter les espaces en fin de ligne
    text = my_replex(text, u"(\n.+?) +?(\r)", r"\1\2")
    # Ensuite : éviter les ébauches
    if not re.search("ébauche", text):
        text = my_replex(text, u"(\n: ?)(.+?)([^\.^,^;^…^\r^\n^!^?^>^}]) ?\r", r"\1\2\3.\n")
    
    if text0 == text:
        print "aucun changement"
    else:
        print u"changements effectués"
        
    return text

def format_pron(text, lang, titre):
###############################################################
#   pour formater la typo de la section de prononciation :    #
#   * format des API / SAMPA                                  #
#   * Ajout d'ébauche, ou des lignes API/SAMPA si manquantes  #
#   (même si elles sont vides                                 #
###############################################################
    print u"  * Formatage de la prononciation :\n  -> ",
    text0 = text
    
    text = my_replex(text, u"\n\*? ?(\{\{API\}\}|\[\[API\]\]|\[\[w:API\|API\]\]) ?:? ?/?([^/]*?)/? ?\n", r"\n* {{API}} : /\2/\n")
    text = my_replex(text, u"\n\*? ?(\{\{SAMPA\}\}|\[\[SAMPA\]\]|\[\[w:SAMPA\|SAMPA\]\]) ?:? ?/?([^/]*?)/? ?\n", r"\n* {{SAMPA}} : /\2/\n")

    API = re.search(u"API", text)
    SAMPA = re.search("SAMPA", text)
    ebauche = re.search(u"ébauche-pron", text)
    
    if not API and not SAMPA:
        print "Vide : ajouts ébauche-API-SAMPA ; ",
        if ebauche:
            text = my_replex(text, u"(pron:--\}\}\r\n\{\{ébauche-pron\|...?\}\})", r"\1" + u"\n* {{API}} : //\r\n* {{SAMPA}} : //\r\n")
        else:
            text = my_replex(text, u"(pron:--\}\}\n)", r"\1" + u"{{ébauche-pron|" + lang + "}}\n* {{API}} : //\r\n* {{SAMPA}} : //\r\n")
            print u"+ ébauche, ",

    # S'il y a API mais pas de contenu : ajout ébauche
    if API and re.search(u"\{\{API\}\} : //|\{\{API\}\} : ?\r", text) and not ebauche:
        print u"ajout d'ébauche : ",
        #text = my_replex(text, u"(pron:--\}\}\n\* \{\{API\}\} )(: //|:)(\r\n)", r"\1\2\3" + u"{{ébauche-pron|" + lang + u"\}\}\n" + r"\2")
        text = my_replex(text, u"(pron:--\}\}\n)", r"\1" + u"{{ébauche-pron|" + lang + u"}}\n")

    # S'il y a déjà API mais pas SAMPA : ajout SAMPA
    if API and not SAMPA:
        print "ajout SAMPA ; "
        text = my_replex(text, u"(pron:--\}\}\n\{\{ébauche-pron\|...?\}\}\n\* \{\{API\}\} : /)([a-z]*?|[a-z]*?\.[a-z]*?|[a-z]*?\.[a-z]*?\.[a-z]*?)(/)", r"\1\2\3" + u"\n* {{SAMPA}} : " + r"/\2/")
        if not re.search("SAMPA", text):
            text = my_replex(text, u"(pron:--\}\}\n\{\{ébauche-pron\|...?\}\}\n\* \{\{API\}\} : /.*?/)", r"\1" + u"\n* {{SAMPA}} : //")
        if not ebauche:
            if not re.search("SAMPA", text):
                text = my_replex(text, u"(\* \{\{API\}\} : /)([a-z]*?|[a-z]*?\.[a-z]*?|[a-z]*?\.[a-z]*?\.[a-z]*?)(/)",  r"\1\2\3" + u"\n* {{SAMPA}} : " + r"/\2/")
            if not re.search("SAMPA", text):
                text = my_replex(text, u"(\* \{\{API\}\} : /.*?/)",  r"\1" + u"\n* {{SAMPA}} : //")

    # S'il y a une ébauche mais pas d'API / SAMPA :
    if ebauche and not API and not SAMPA:
        text = my_replex(text, u"(\{\{ébauche-pron\|...?\}\})", r"\1" + u"\n* {{API}} : //\n* {{SAMPA}} : //")    

            
    if text0 == text:
        print "aucun changement"
    else:
        print u"changements effectués"
    return text

def rapatri_cat(text):
##############################################################
#   pour rapatrier les cat qui se baladent...                #
##############################################################
    print u"Recherche de catégories qui trainent :\n  -> ",
    text0 = text


    # Repérage : y a-t-il des catégories qui trainent ?
    catbal = True
    catentro = []
    while catbal:
        catbal = re.search(u"\[\[Catégorie:", text)
        if catbal:
            # Cat repérée ! Découpage, muolinage et relancé jusqu'à vidange complète
                debutcat = catbal.start()
                contenucat = text[debutcat:]
                fincat = re.search("\]\]", contenucat).start()
                contenucat = contenucat[:fincat] + "]]"
                catentro.append(contenucat)
                
                text = my_repl(text, contenucat, "")
                text = my_repl(text, "\n\n", "\n")
                    
        elif catentro:
            print u"Catégories repêchées, ",
        else:
            print u"Pas de cat, ",
            
    # Repérage : y a-t-il des interwikis qui trainent ?
    itwbal = True
    itwentro = []
    while itwbal:
        itwbal = re.search(u"\[\[[a-z]{2,3}:", text)
        if itwbal:
            # interwiki repérée ! Découpage, muolinage et relancé jusqu'à vidange complète
                debutitw = itwbal.start()
                contenuitw = text[debutitw:]
                finitw = re.search("\]\]", contenuitw).start()
                contenuitw = contenuitw[:finitw] + "]]"
                itwentro.append(contenuitw)
                
                text = my_repl(text, contenuitw, "")
                text = my_repl(text, "\n\n", "\n")

        elif itwentro:
            print u"Interwikis repêchées. ",
        else:
            print u"Pas d'interwiki. ",



    if catentro:
        print "cat : ", catentro,
    if itwentro:
        print "itw : ", itwentro,
    
    
    # A faire ci-dessus
    
    if text0 == text:
        print "aucun changement"
    else:
        print u"changements effectués"
        
    return text, catentro, itwentro

def format_cat(text, titre, catentro, itwentro):
##############################################################
#   pour formater la liste des catégories et des interwikis  #
##############################################################
    print u"\nFormatage des catégories :\n  -> ",
    
# Ajout des catégories et interwikis qui trainaient
    #Réunion des cat et interwikis :
    catot = u''
    itot = u''
    for cati in catentro:
        catot += cati
    for it in itwentro:
        itot += it
    text = text + catot + itot

    text0 = text
    text = my_replex(text, u"\[\[(C|c)at(e|é)gor(ie|y):([^]]+?)\]\]", r"[[-cat:\4:tac-]]")
    
    parties = text.split(u"[[")
    list_cat = u''
    list_itw = u''
    ncat=0
    nitw=0

    for i, p in enumerate(parties):
        # Nettoyage éventuel
        p2 = my_replex(p, u"(\n|\r|\n )", r"")
        # S'il le trouve : c'est une catégorie
        if re.search(u"-cat:", p2):
            ncat +=1
            list_cat += u"\n[[" + p2
        # Sinon : c'est un interwiki
        elif (p2 <> u""):
            nitw +=1
            list_itw += u"\n[[" + p2
            
    #print "\nlistcat : \n", list_cat
    #print "\nlistitw : \n", list_itw

# Reconstruction des cat et itw
    text = "\n"
    if list_cat <> u'':
        text = text + list_cat
        if list_itw <> u'':
            text = text + "\n" + list_itw
    elif list_itw <> u'':
        text = text + list_itw

    text = my_replex(text, u"\[\[-cat:(.+?):tac-\]\]", u"[[Catégorie:" + r"\1]]")

    print ncat, " cat et ", nitw, "interwikis  ; ",
    
    if text0 == text:
        print "aucun changement"
    else:
        print u"changements effectués"

    #print "CAT : \n------\n", text, "\n------\n"
        
    return text

def corrections(text, titre):
############################################################
#   Optionnel, pour corriger toutes sortes d'erreurs       #
############################################################
    
# Un peu de typo complémentaire
    text = my_repl(text, u"\n{{-", u"\n\n{{-")
    text = my_repl(text, u"\n\n{{-}}", u"\n{{-}}")

# Pour les liens définitions -> synonymes etc.
    text = my_replex(text, u"\n ?\* ?'?'?'?(.+?)'?'?'? ?\(sens (..?|..?|..?,..?|..?,..?,..?)\) :", r"\n\n'''\1''' (\2) :")
    text = my_replex(text, u"\n'?'?'?(.+?)'?'?'? ?\(sens (..?|..?|..?,..?|..?,..?,..?)\) :", r"\n\n'''\1''' (\2) :")
    text = my_replex(text, u"(-\}\})\n+('''.+?''')", r"\1\n\2")

    text = my_repl(text, u"\n{{=", u"\n\n{{=")
    text = my_repl(text, u"=}}\n\n{{-", u"=}}\n{{-")

    text = my_replex(text, u"(\{\{ébauche\|[^\}]+?\}\}\n)\n", r"\1")
    
    return text

def corrections2(text, titre):
######################################################################
#   Optionnel, autres corrections sans rapport avec la structure     #
######################################################################
    # Lien Wikipédia
    text = my_replex(text, u"\* \[\[w:(.+?)\|(.+?)]] sur Wikipédia", r"{{WP|\1|\2}}")
    text = my_replex(text, u"\* \[\[w:(.+?)]] sur Wikipédia", r"{{WP|\1|\1}}")
    text = my_replex(text, u"\n\*? ?\{\{Wikipé?e?dia\}\}", r"\n{{WP}}")

    # Tableau modèle simple
    text = my_replex(text, u'\{\| border=0 width=100%\n\|-\n\|bgcolor=.+? valign=top width=48% style="border:1px solid #aaaaaa; padding:5px;" \|\n\{\|',
                     r'{{(}}')
    text = my_replex(text, u'\|\}\n\| width=1% \|\n\|bgcolor=.+? valign=top width=48% style="border:1px solid #aaaaaa; padding:5px;" \|\n\{\|',
                     r'{{-}}')
    text = my_repl(text, u'|}\n|}', r'{{)}}')
    
    # Correction import allemand raté
    text = my_repl(text, u"/}}, ''Plural:'' {{Lauʦchrift|/", u"//")
    text = my_repl(text, u"/}}, ''Plural:'' {{Lauts)chrift|/", u"//")
    text = my_repl(text, u"/}}, {{Pl./", u"//")
    
    return text

def post_corrections(text, titre):
######################################################################
#   Correction pour que le bot fonctionne mieux                      #
######################################################################
    # élimination de tous les espaces
    text = my_replex(text, u"[\r\n]+", u"\n")
    # Modèles de sections standards
    text = my_replex(text, u"\{\{-locution-\| ?adverbiale? ?\}\}", "{{-loc-adv-}}")
    text = my_replex(text, u"\{\{-locution-\| ?\}\}", "{{-loc-}}")
    
    text = my_replex(text, u"\{\{-article-\|indéfini\}\}", "{{-art-indef-}}")
    text = my_repl(text, u"{{-article-|indéfini}}", "{{-art-indef-}}")
    text = my_repl(text, u"{{-article-|indéfini}}", "{{-art-indef-}}")
    text = my_replex(text, u"\{\{-article-\|défini\}\}", "{{-art-def-}}")
    text = my_replex(text, u"\{\{-article-\|partitif\}\}", "{{-art-part-}}")
    text = my_replex(text, u"===?=? ?(v|V)oir aussi ?===?=?", r"{{-voir-}}")

    # Divers
    text = my_replex(text, u"(\{\{ébauche-[^\}]+?\}\}) ?(\{\{-)", r"\1\n\2")

    return text

def processus(resultat, titre):
#############################
#   Processus complet       #
#############################
    resultat = post_corrections(resultat, titre)
    resultat = balisage(resultat, titre)
    print "\n\n" + 100*"=" + "\n\n"
    resultat = format_article(resultat, titre)
    resultat = debalisage(resultat, titre)
    resultat = corrections(resultat, titre)
    resultat = corrections2(resultat, titre)
    
    # Affiche a page complète pour vérifier la mise en page
    titre = "\r\n" + 100*"-" + "\r\n" + resultat + "\r\n" + 100*"-" + "\r\n"
    wikipedia.output(titre)
    #print titre
    
    return resultat


##################################################################
#   Vérifie que le titre est bien normal (hors annexe surtout)   #
##################################################################
def check_titre(titre):
    saute = False
    excep = ["Annexe:", "Utilisateur:", "Discussion Utilisateur:"]
    for sau in excep:
        if re.search(sau, titre):
            saute = True
    return saute

##################################################################
#   Vérifie que le texte est réellement modifié (problème avec   #
#   les regex observé)                                           #
##################################################################
def check_diff(avant, apres):
    saute = False
    avant = my_replex(avant, "\r|\n", "")
    apres = my_replex(apres, "\r|\n", "")
    
    if avant == apres:
        saute = True
    return saute

#---------------------------------------------------------------
# Suite : normal
#---------------------------------------------------------------

class ReplaceRobot:
    def __init__(self, generator, replacements, exceptions = [], regex = False, acceptall = False):
        self.generator = generator
        self.replacements = replacements
        self.exceptions = exceptions
        self.regex = regex
        self.acceptall = acceptall

    def checkExceptions(self, original_text):
        """
        If one of the exceptions applies for the given text, returns the 
        substring which matches the exception. Otherwise it returns None.
        """
        for exception in self.exceptions:
            if self.regex:
                hit = exception.search(original_text)
                if hit:
                    return hit.group(0)
            else:
                hit = original_text.find(exception)
                if hit != -1:
                    return original_text[hit:hit + len(exception)]

    def doReplacements(self, original_text):
        """
        Returns the text which is generated by applying all replacements to the
        given text.
        """
        
        new_text = original_text
        for old, new in self.replacements:
            if self.regex:
                new_text = old.sub(new, new_text)
            else:
                new_text = new_text.replace(old, new)
        return new_text
        
    def run(self):
        """
        Lance le robot.
        """
        # Run the generator which will yield Pages which might need to be
        # changed.
        for page in self.generator:
            try:
                # Chargement depuis le wiki
                original_text = page.get()
                match = self.checkExceptions(original_text)
                if not page.canBeEdited():
                    wikipedia.output(u'Je saute la page protégée %s' % page.title())
                    continue
            except wikipedia.NoPage:
                wikipedia.output(u'Je n\'ai pas trouvé la page %s' % page.title())
                continue
            except wikipedia.IsRedirectPage:
                continue

            match2 = check_titre(page.title())
            # test
            match2 = False
            
            # SAute les pages qui ont des exceptions de contenu, de titre ou des <!-- (difficile à gérer par bot)
            if not re.search(u"pron", original_text):
                wikipedia.output(u' %s sautée car ne contient pas de prononciation' % (page.title()))
                chemin = open("log xml/format/nopron-.txt", "a")
                chemin.write("\n* [[" + page.title().encode('utf8') + "]]")
                chemin.close()
            elif match:
                wikipedia.output(u' %s sautée car exception' % (page.title()))
            elif match2:
                wikipedia.output(u' %s sautée car le titre n\'est pas dans le namespace général' % (page.title()))
            elif re.search(u"<!--", original_text):
                wikipedia.output(u' %s sautée car le texte contient des <!-- (logué)' % (page.title()))
                chemin = open("log xml/format/bug-.txt", "a")
                titre = page.title().encode('utf8')
                chemin.write("\n* [[" + titre + "]]")
                chemin.close()
                
            else:
#################################################################
                # Processus de formatage :
                new_text = processus(original_text, page.title())
#################################################################
                if new_text == original_text:
                    wikipedia.output(u'Aucun changements nécessaires dans %s' % page.title())
                if check_diff(original_text, new_text):
                    wikipedia.output(u'Aucun changements nécessaires dans %s (vérification de deuxième ordre)' % page.title())
                    
                else:
                    wikipedia.output(u'<<<>>> %s <<<>>>>' % page.title())
                    wikipedia.showDiff(original_text, new_text)
                    textdiff = wikipedia.textDiff(original_text, new_text, page.title())
                    pronoui = re.search("pron", textdiff)
                    if not pronoui:
                        for typ in types_de_mot0:
                            pron1 = re.search(typ, textdiff)
                            if pron1:
                                pronoui = True
                    if not pronoui:
                        if not self.acceptall:
                            choice = wikipedia.inputChoice(u'Pas de prononciation changée, loguer ou continuer ?',  ['Log', 'Cont', 'All'], ['l', 'c', 'a'], 'N')
                            if choice in ['c', 'C']:
                                print "Passé sans changé ni logé"
                            if choice in ['a', 'A']:
                                self.acceptall = True
                        if self.acceptall or choice in ['l', 'L']:
                                chemin = open("log xml/format/paspron.txt", "a")
                                titre = page.title().encode('utf8')
                                chemin.write("\n* [[" + titre + "]]")
                                chemin.close()
                    elif not self.acceptall and pronoui:
                        choice = wikipedia.inputChoice(u'Accepter les changements ?',  ['Yes', 'No', 'All'], ['y', 'N', 'a'], 'N')
                        if choice in ['a', 'A']:
                            self.acceptall = True
                    if pronoui:
                        if self.acceptall or choice in ['y', 'Y']:
                            page.put(new_text)
                            wikipedia.logDiff(original_text, new_text, page.title(), fichierlog)
    
def main():
    gen = None
    
    # Choix de l'origine de la liste des pages à changer
    source = None
    
    # Un tableau qui reçoit les paramètres de la ligne de commande directement :
    # Le premier est le texte à changer, le second le remplacement
    # INUTILE POUR UNE UTILISATION AVANCEE
    commandline_replacements = []

    # Liste de remplacements (et non pas seulement deux)
    replacements = []
    
    # Textes d'exceptions
    exceptions = []
    
    # Choix d'utilisation des expressions régulières pour les remplacements et les exceptions : oui/non
    regex = False
    
    # Remplacements prédéfinis : oui/non
    fix = None
    
    # the dump's path, either absolute or relative, which will be used when source
    # is 'xmldump'.
    textfilename = None
    
    # Nom de la catégorie si la liste des changements en est une
    categoryname = None
    
    # pages données à modifier via la ligne de commande 
    pageNames = []
    
    # Page de référence via sa liste de suivi
    referredPageName = None
    
    # Oui quand always: ou quand on demande a
    acceptall = False
    
    # quel namespace ? Rien par défaut pour : tous
    namespaces = []
    
    # Page de départ pour le paramètre start
    startpage = None
    
    # Résumé par défaut msg (début de prog)
    wikipedia.setAction(wikipedia.translate(wikipedia.getSite(), msg))

    # Lecture de la ligne de commande à la recherche d'arguments
    for arg in sys.argv[1:]:
        arg = wikipedia.argHandler(arg, 'replace')

    # Y a-t-il des paramètres ?
        if arg:
            
        # Si expressions régulières
            if arg == '-regex':
                regex = True

        # un fichier de texte donné
            elif arg.startswith('-file'):
                if len(arg) == 5:
                    textfilename = wikipedia.input(u'Please enter the filename:')
                else:
                    textfilename = dossier_log + arg[6:]
                source = 'textfile'
                
        # Une catégorie donnée
            elif arg.startswith('-cat'):
                if len(arg) == 4:
                    categoryname = wikipedia.input(u'Please enter the category name:')
                else:
                    categoryname = arg[5:]
                source = 'category'
                
        # Une page donnée
            elif arg.startswith('-page'):
                if len(arg) == 5:
                    pageNames.append(wikipedia.input(u'Which page do you want to chage?'))
                else:
                    pageNames.append(arg[6:])
                source = 'singlepage'
                
        # Liste de suivi d'une page donnée
            elif arg.startswith('-ref'):
                if len(arg) == 4:
                    referredPageName = wikipedia.input(u'Links to which page should be processed?')
                else:
                    referredPageName = arg[5:]
                source = 'ref'
                
        # Pour faire toutes les pages à partir de...
            elif arg.startswith('-start'):
                if len(arg) == 6:
                    firstPageTitle = wikipedia.input(u'Which page do you want to chage?')
                else:
                    firstPageTitle = arg[7:]
                source = 'allpages'

        # Donner une exception
            elif arg.startswith('-except:'):
                exceptions.append(arg[8:])

        # Pour faire un remplacement pré-défini
            elif arg.startswith('-fix:'):
                fix = arg[5:]

        # Ne pas demander s'il faut changer
            elif arg == '-always':
                acceptall = True

        # ne remplacer que dans un namespace spécifique
            elif arg.startswith('-namespace:'):
                namespaces.append(int(arg[11:]))

        # SINON le paramètre est enregistré dans commandline_replacements
            else:
                commandline_replacements.append(arg)

    # Si on a bien deux paramètres jouant le rôle de texte à remplacer et de texte de remplacement, alors on les met dans les changements à effectuer
    if (len(commandline_replacements) == 2 and fix == None):
        replacements.append((commandline_replacements[0], commandline_replacements[1]))

    # Fabrication d'un message automatique dans ce cas-là -... +...
        wikipedia.setAction(wikipedia.translate(wikipedia.getSite(), msg ) % ' (-' + commandline_replacements[0] + ' +' + commandline_replacements[1] + ')')

    # Si aucune source n'est donnée, on les demande
    #elif fix == None:
    #   old = wikipedia.input(u'Texte à remplacer :')
    #    new = wikipedia.input(u'Texte de remplacement :')
    #    change = '(-' + old + ' +' + new
    #    replacements.append((old, new))
    #    while True:
    #        old = wikipedia.input(u'Tapez un nouveau texte ou bien entré pour continuer :')
    #        if old == '':
    #            change = change + ')'
    #           break
    #       new = wikipedia.input(u'Nouveau texte :')
    #       change = change + ' & -' + old + ' +' + new
    #       replacements.append((old, new))
    #   default_summary_message =  wikipedia.translate(wikipedia.getSite(), msg) % change
    #   wikipedia.output(u'Résumé par défaut : %s' % default_summary_message)
    #   summary_message = wikipedia.input(u'Message par défaut ou taper un message personnalisé :')
    #   if summary_message == '':
    #       summary_message = default_summary_message
    #   wikipedia.setAction(summary_message)
    #else:

    
    # Compilation des expressions pour gagner du temps
    if regex:
        for i in range(len(replacements)):
            old, new = replacements[i]
            oldR = re.compile(old, re.UNICODE)
            replacements[i] = oldR, new
        for i in range(len(exceptions)):
            exception = exceptions[i]
            exceptionR = re.compile(exception, re.UNICODE)
            replacements[i] = exceptionR

    # Création des listes des pages à changer à partir des sources
    # fichier texte
    if source == 'textfile':
        gen = pagegenerators.TextfilePageGenerator(textfilename)
    # Catégorie
    elif source == 'category':
        cat = catlib.Category(wikipedia.getSite(), categoryname)
        gen = pagegenerators.CategorizedPageGenerator(cat)
    # Une page
    elif source == 'singlepage':
        pages = [wikipedia.Page(wikipedia.getSite(), pageName) for pageName in pageNames]
        gen = iter(pages)
    # Toutes les pages
    elif source == 'allpages':
        namespace = wikipedia.Page(wikipedia.getSite(), firstPageTitle).namespace()
        gen = pagegenerators.AllpagesPageGenerator(firstPageTitle, namespace)
    # Une référence
    elif source == 'ref':
        referredPage = wikipedia.Page(wikipedia.getSite(), referredPageName)
        gen = pagegenerators.AllReferringPageGenerator(referredPage)
# S'il n'y a aucune source : montrer l'aide
    elif source == None or len(commandline_replacements) not in [0, 2]:
        # syntax error, show help text from the top of this file
        wikipedia.output(__doc__, 'utf-8')
        wikipedia.stopme()
        sys.exit()
    # Si l'on donne un namespace, on restreint alors la liste générée avec un filtre
    if namespaces != []:
        gen = pagegenerators.NamespaceFilterPageGenerator(gen, namespaces)

    # On charge la liste gen, avec un nombre de...
    preloadingGen = pagegenerators.PreloadingGenerator(gen, pageNumber = 20)
    # Mise en place du robot à partir de tous les éléments donnés
    bot = ReplaceRobot(preloadingGen, replacements, exceptions, regex, acceptall)

    # Lancement !
    bot.run()


if __name__ == "__main__":
    try:
        main()
    finally:
        wikipedia.stopme()