#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Ce truc était un robot, mais maintenant,
c’est un assistant pour créer des articles.
"""
import os, sys
import re
import time
import gtk
import neti
try: import helpbro
except:
class Foo:''
helpbro = Foo(); helpbro.HelpBrowser=lambda:''
print "Vous n’aurez pas d’aide."
interface = neti.interface
interface.DELAY = 5
interface.SLEEP_POINT_TIME = 1
interface.BOT = False
if len (sys.argv) > 1: interface.USER_NAME = sys.argv
os.chdir (sys.path)
class ArticleError (Exception): pass
class ArticleFr:
"""
Classe pour créer le texte d’un article, selon le modèle
canonique du Wiktionnaire francophone.
Utilisation basique :
mon_article = ArticleFr ("oiseau", "nom", "fr", "m")
mon_article.set_pron ("wazo")
mon_article.add_def ("{{ucf|volatile}} à ].",
"''Fais comme l’'''oiseau''', et tout le bazar.''",
"''Les chauves-souris ne sont pas des '''oiseaux'''.''")
mon_article.add_def ("Seconde définition", "''Exemple pour la seconde définition.''")
mon_article.put_on_wikt ()
On vient de créer un article, de lui mettre des définitions et de l’ajouter
au wiktionnaire.
Mais avant d’appeler put_on_wikt (), on peut ajouter d’autres informations :
* images :
mon_article.add_img ("Mésange bleue.JPG", "La mésange bleue est un '''oiseau'''")
* traductions (avec genre ou romanisation optionnels)
mon_article.add_trad ("bird", "en")
mon_article.add_trad ("Vogel", "de", genre="m")
mon_article.add_trad ("새", "ko", roman="ㅅ|ㅐ")
* synonymes, antonymes, holonymes, méronymes, hypéronymes, hyponymes, etc.
mon_article.add_hyper ("animal", "m")
mon_article.add_hypo ("passereau", "m")
mon_article.add_hypo ("rapace", "m")
mon_article.add_mero ("aile", "f")
mon_article.add_mero ("plume", "f")
* expressions
mon_article.add_exp ("le petit oiseau va sortir")
mon_article.add_exp ("drôle d’oiseau", "m")
mon_article.add_exp ("oiseau de malheur", "m")
Et on peut invoquer render () si on veut voir le résultat (par exemple, pour
faire une vérification avant de le mettre sur le wiki).
print "------Mon Article------\n" + mon_article.render ()
"""
def __init__ (self, nom="", categ="", lang="", genre=""):
self.nom = nom
self.genre = genre
self.pron = ""
self.content = ""
self.lang = lang
self.categ = categ
self.imgs =
self.defs =
self.trads = {}
self.voirwp = ""
self.sect_orthoalt = "" # autres orthographes
self.sect_syn = ""
self.sect_qsyn = ""
self.sect_ant = "" # contraires
self.sect_drv = "" # mots dérivés
self.sect_apr = "" # mots apparentés étymologiquement
self.sect_voc = "" # mots du même champ lexiacal
self.sect_drvint = "" # dérivés étrangers
self.sect_exp = "" # expressions
self.sect_dial = "" # variantes dialectales
self.sect_trad = "" #
self.sect_hyper = "" # mots plus généraux
self.sect_hypo = "" # mots plus précis
self.sect_holo = "" # le mot en fait partie (maison>'''toit''')
self.sect_mero = "" # parties du mot ('''toit'''>tuile)
self.sect_tropo = "" # verbe hyponyme (tuer>égorger)
self.sect_voir = ""
def render (self):
if "" in (self.nom, self.categ, self.lang):
try: raise ArticleError, "il manque le nom, la catégorie grammaticale ou la langue."
except ArticleError, msg: sys.stderr.write ("Warning: %s\n"%msg)
content =
self.make_sect_trad ()
## essentiel
content.append ("== {{=%s=}} ==" % self.lang)
content.append ("{{ébauche|%s}}" % self.lang)
content.append ("{{-étym-}}\n: {{ébauche-étym|fr}}\n")
content.append ("{{-%s-|%s}}" %
(self.categ, self.lang))
for img in self.imgs:
content.append ("]"
% img)
ligne_forme = "'''%s'''"%self.nom
if self.pron: ligne_forme += " {{pron|%s|%s}}"%(
self.pron, self.lang)
if self.genre: ligne_forme += " {{%s}}"%self.genre
content.append (ligne_forme)
for definition in self.defs:
content.append (definition)
## bonus et trads
for bonus_trad in (
self.sect_orthoalt,
self.sect_syn,
self.sect_qsyn,
self.sect_ant,
self.sect_drv,
self.sect_apr,
self.sect_voc,
self.sect_drvint,
self.sect_exp,
self.sect_dial,
self.sect_trad,
self.sect_hyper,
self.sect_hypo,
self.sect_holo,
self.sect_mero,
self.sect_tropo,
self.sect_voir):
if bonus_trad: content.append ("\n" + bonus_trad)
content.append ("\n" + self.cledetri())
return "\n".join (content)
def cledetri (self):
if self.lang=="ko": return ""
nom = unicode (self.nom, "utf-8").lower ()
nom = re.sub (u"", "e", nom)
nom = re.sub (u"", "a", nom)
nom = re.sub (u"ç", "c", nom)
nom = re.sub (u"", "i", nom)
nom = re.sub (u"", "o", nom)
nom = re.sub (u"", "u", nom)
nom = re.sub (u"ñ", "n", nom)
nom = re.sub (u"’", "", nom)
nom = nom.encode ("utf-8")
if nom==self.nom: return "{{clé de tri}}"
else: return "{{clé de tri|%s}}"%nom
def set_lang (self, lang):
self.lang = lang
def set_categ (self, categ):
self.categ = categ
def set_genre (self, genre):
self.genre = genre
def set_nom (self, nom):
self.nom = nom
def add_img (self, img, legende="", n=1):
self.imgs.append ((img, legende, n))
def add_def (self, definition, *exemples):
tmp_def = "" # "# "
if isinstance (definition, tuple):
return
precisions, definition = definition, definition
for prec in precisions:
if prec in LISTE_PRECISIONS:
tmp_def += "{{%s}} "%prec
else:
tmp_def += "{{term|%s}} "%prec
tmp_def += definition
for i in exemples:
if i==":": i = "#*: "+i
else: i = "#* "+i
tmp_def += "\n" + i
self.defs.append (tmp_def)
def add_syn (self, syn, comment=""):
if not self.sect_syn: self.sect_syn = "{{-syn-}}"
if comment: comment= " "+comment
self.sect_syn += "\n* ]%s"%(syn, comment)
def add_qsyn (self, qsyn, comment=""):
if not self.sect_qsyn: self.sect_qsyn = "{{-q-syn-}}"
if comment: comment= " "+comment
self.sect_qsyn += "\n* ]"%(qsyn, comment)
def add_ant (self, ant, comment=""):
if not self.sect_ant: self.sect_ant= "{{-ant-}}"
if comment: comment= " "+comment
self.sect_ant += "\n* ]%s"%(ant, comment)
def add_drv (self, drv, comment=""):
if not self.sect_drv: self.sect_drv= "{{-drv-}}"
if comment: comment= " "+comment
self.sect_drv += "\n* ]%s"%(drv, comment)
def add_apr (self, apr, comment=""):
if not self.sect_apr: self.sect_apr= "{{-apr-}}"
if comment: comment= " "+comment
self.sect_apr += "\n* ]%s"%(apr, comment)
def add_voc (self, voc, comment=""):
if not self.sect_voc: self.sect_voc= "{{-voc-}}"
if comment: comment= " "+comment
self.sect_voc += "\n* ]%s"%(voc, comment)
def add_drvint (self, drvint, comment=""):
if not self.sect_drvint: self.sect_drvint= "{{-drvint-}}"
if comment: comment= " "+comment
self.sect_drvint += "\n* ]%s"%(drvint, comment)
def add_exp (self, exp, comment=""):
if not self.sect_exp: self.sect_exp= "{{-exp-}}"
if comment: comment= " "+comment
self.sect_exp += "\n* ]%s"%(exp, comment)
def add_dial (self, dial, comment=""):
if not self.sect_dial: self.sect_dial= "{{-dial-}}"
if comment: comment= " "+comment
self.sect_dial += "\n* ]%s"%(dial, comment)
def add_trad (self, trad, lang, genre="", roman=""):
if genre: genre=" {{%s}}"%genre
if not self.trads.has_key (lang):
self.trads =
if lang=="ko" and roman:
v = ""
if self.categ == "verb" or self.categ == "adj":
v="|verbe=1"
roman = "{{ko-roman|%s%s}}"%(roman, v)
self.trads .append ("{{trad|ko|%s|R=%s}}"%(trad,roman))
elif roman:
self.trads .append ("{{trad|%s|%s|R=%s}}"%(lang, trad,roman))
else:
self.trads .append ("{{trad|%s|%s}}%s"%(lang, trad, genre))
def make_sect_trad (self):
trads_sav={}
if not self.trads: return
self.sect_trad= "{{-trad-}}"
self.sect_trad += "\n{{(}}"
# d’abord les langues qu’on sait trier
for lang in ("de", "en", "nds", "ko", "es", "eo", "fr", "pt"):
if self.trads.has_key (lang):
self.sect_trad += "\n* {{T|%s}} : %s"%(lang, ", ".join (self.trads))
trads_sav=self.trads.pop (lang)
# ensuite les autres
for lang in self.trads:
self.sect_trad += "\n* {{T|%s}} : %s"%(lang, ", ".join (self.trads))
trads_sav=self.trads.pop (lang)
self.trads=trads_sav
self.sect_trad += "\n{{)}}"
def add_hyper (self, hyper, comment=""):
if not self.sect_hyper: self.sect_hyper= "{{-hyper-}}"
if comment: comment= " "+comment
self.sect_hyper += "\n* ]%s"%(hyper, comment)
def add_hypo (self, hypo, comment=""):
if not self.sect_hypo: self.sect_hypo= "{{-hypo-}}"
if comment: comment= " "+comment
self.sect_hypo += "\n* ]%s"%(hypo, comment)
def add_holo (self, holo, comment=""):
if not self.sect_holo: self.sect_holo= "{{-holo-}}"
if comment: comment= " "+comment
self.sect_holo += "\n* ]%s"%(holo, comment)
def add_mero (self, mero, comment=""):
if not self.sect_mero: self.sect_mero= "{{-méro-}}"
if comment: comment= " "+comment
self.sect_mero += "\n* ]%s"%(mero, comment)
def add_tropo (self, tropo, comment=""):
if not self.sect_tropo: self.sect_tropo= "{{-tropo-}}"
if comment: comment= " "+comment
self.sect_tropo += "\n* ]%s"%(tropo, comment)
def add_voir (self, voir, comment=""):
if not self.sect_voir: self.sect_voir= "{{-voir-}}"
if comment: comment= " "+comment
self.sect_voir += "\n* ]%s"%(voir, comment)
def set_pron (self, pron):
self.pron = pron
def add_voirWP (self, lien=""):
"ajoute un lien vers Wikipédia"
if not self.sect_voir: self.sect_voir = "{{-voir-}}"
if lien: lien="|"+lien
self.sect_voir += "\n* {{WP%s}}"%lien
def put_on_wikt (self, prefix="Utilisateur:Eiku/brouillons/"):
"""Crée une page."""
pagename = prefix + self.nom
page = neti.Page (pagename)
render = self.render ()
if page.exists (): raise ArticleError, "La page existe déjà."
commentaire = "(Assisté) Création: %s"%render.replace ("\n"," ")
if not page.create (commentaire, render):
print "Échec de l’écriture de la page (probablement un problème de connexion à Internet)"
print "Sauvegarde de la page pour création ultérieure."
# sauvegarde de la page dans une liste de pages à créer
numero = 0
filename_a_creer = "pages_a_creer/%02d"%numero
while os.path.exists (filename_a_creer):
numero += 1
filename_a_creer = "pages_a_creer/%02d"%numero
open (filename_a_creer, "w").write (pagename + "\n" + self.render())
else:
print "Réussite de l’écriture de la page."
def replace_on_wikt (self, prefix="Utilisateur:Eiku/brouillons/"):
"""Remplace une page existante sans confirmation."""
pagename = prefix + self.nom
page = neti.Page (pagename)
render = self.render ()
page.write ("(bot) Remplacé par: %s"%render.replace ("\n"," "),
render)
'''
class CompEntry (gtk.Entry):
def __init__ (self):
gtk.Entry.__init__ (self)
self.completer = gtk.EntryCompletion ()
'''
class GUI_Definition (gtk.VBox):
def __init__ (self, parent):
gtk.VBox.__init__ (self)
self.papa = parent
self.papa.pack_start(self, expand=True, fill=True)
# textarea
sw = gtk.ScrolledWindow ()
tv = gtk.TextView ()
sw.add (tv)
sw.set_policy( gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
tv.set_right_margin (13)
tv.set_left_margin (13)
tv.set_wrap_mode (gtk.WRAP_WORD)
tv.set_accepts_tab (False)
self.pack_start (sw, expand=True, fill=True)
tv.show_all ()
self.buf = tv.get_buffer()
self.tv = tv
def get_def (self):
buf = self.buf
text = buf.get_text (buf.get_start_iter (), buf.get_end_iter ())
#if text.startswith ("# "): text = text
return text
class GUI_ArticleCreator (gtk.Window):
def __init__ (self):
gtk.Window.__init__ (self)
self.set_default_size(600, 400)
self.set_title ("Ajouter un mot")
box = gtk.VBox ()
self.table = gtk.Table (6, 2)
self.table.set_col_spacing (0, 10)
box.pack_start (self.table, expand=False, fill=True)
self.add (box)
self.entries =
self.entry_focused = 0
self.win = gtk.Window ()
#self.definition
self.funcs =
self.nlignes = 1
# Mot vedette
self.vedette = self.add_entry ()
# Langue
self.langue = self.add_entry ("Langue")
self.langue.set_text ("fr")
# Catégorie
def on_categ_changed ():
txt = self.categ.get_text ()
if txt in ("nom", "loc-nom"):
self.genre.show ()
else:
self.genre.set_text ("")
self.genre.hide ()
self.categ = self.add_entry ("Catégorie")
self.categ.set_text ("nom")
self.categ.connect ("changed", lambda *w: on_categ_changed ())
# Genre
self.genre = self.add_entry ("Genre")
# Prononciation
self.pron = self.add_entry ("Prononciation")
# Définitions
self.definitions = GUI_Definition (box)
self.entries.append (self.definitions.tv)
def on_anything_changed (*w):
self.on_valide ()
for e in :
e.connect ("changed", on_anything_changed)
# bonus
pass
# Bouton
hb = gtk.HBox ()
box.pack_start (hb, expand=False, fill=True)
#bouton = gtk.Button ("Prévisualiser")
#bouton.connect ("clicked", lambda *w: self.on_valide ())
#hb.pack_start (bouton, expand=True, fill=False)
bouton_help = gtk.Button ("Aide")
bouton_help.connect ('clicked', lambda *w: helpbro.HelpBrowser())
hb.pack_start (bouton_help, expand=True, fill=False)
bouton_help_edit = gtk.Button ("(edit)")
bouton_help_edit.connect ('clicked', lambda *w: os.system('gvim wikt-help.txt'))
hb.pack_start (bouton_help_edit, expand=True, fill=False)
bouton_send = gtk.Button ("Envoyer")
bouton_send.connect ("clicked", lambda *w: self.on_send ())
hb.pack_start (bouton_send, expand=False, fill=False)
# Preview
self.prev = exp = gtk.Expander ()
sw = gtk.ScrolledWindow ()
sw.set_policy (gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
tv = gtk.TextView ()
tv.set_wrap_mode (gtk.WRAP_WORD)
tv.set_editable (False)
sw.set_size_request(200, 300)
self.prev_buf = tv.get_buffer ()
sw.add (tv)
exp.add (sw)
box.add (exp)
exp.set_expanded (False)
self.continuer = True
on_anything_changed ()
def focus_next (self, *w):
self.entry_focused = (self.entry_focused + 1) % len (self.entries)
self.entries .grab_focus ()
def add_entry (self, label=None):
entry = gtk.Entry ()
a = gtk.EXPAND | gtk.FILL
b = gtk.SHRINK | gtk.FILL
if label:
self.table.attach (gtk.Label (label), 0, 1, self.nlignes, self.nlignes + 1, b, b)
self.table.attach (entry, 1, 2, self.nlignes, self.nlignes + 1, a,b)
else:
self.table.attach (entry, 0, 2, self.nlignes, self.nlignes + 1, a,b)
self.entries.append (entry)
entry.connect ("activate", self.focus_next)
self.nlignes += 1
return entry
def on_valide (self):
art = ArticleFr ()
art.set_nom (self.vedette.get_text())
art.set_genre (self.genre.get_text ())
art.set_lang (self.langue.get_text ())
art.set_categ (self.categ.get_text ())
art.set_pron (self.pron.get_text ())
art.defs =
art.add_def (self.definitions.get_def ())
self.prev.set_expanded (True)
self.prev_buf.set_text (art.render ())
return art
def on_send (self):
art = self.on_valide ()
#art.put_on_wikt ()
art.put_on_wikt (prefix='')
self.destroy ()
self.continuer = True
def on_destroy (self):
self.destroy ()
gtk.main_quit ()
self.continuer = False
def run (self):
self.connect ('destroy', lambda *w: self.on_destroy())
self.show_all ()
gtk.main ()
return self.continuer
def main ():
"""Appelle juste l’interface"""
# Interface
while GUI_ArticleCreator ().run (): ''
if __name__ == "__main__":
try: main ()
except KeyboardInterrupt: print "\033[31mLeaving: User typed Ctrl+C.\033[0m"