C'est un module python fournissant une ou plusieurs fonctions supplémentaires à pyCoinCoin et s'intégrant automatiquement au logiciel. On peut distinguer plusieurs sortes de plug-ins en fonction du genre de traitement qu'ils font :
Physiquement, cela consiste en un ou plusieurs fichiers .py situés dans le répertoire plugins de pycc ou dans le répertoire .pycoincoin/plugins de l'utilisateur.
Sous pyCoinCoin, les plug-ins peuvent être utilisé de 5 manières différentes :
Au démarrage, pyCoinCoin charge tous les fichiers .py qu'il trouve dans son répertoire plugins ainsi que ceux du répertoire .pycoincoin/plugins de l'utilisateur. Dans ces fichiers, les plugins sont des classes python, repérées par leur nom obligatoirement préfixé par "coin_". Ces classes héritent de la classe générique CoinPlugin.
Voici les attributs spécifiques que la classe de plug-in doit définir :
Une classe de plug-in doit implémenter au minimum une méthode process, dont voici le profil :
def process(self, trib, post, text)
Cette méthode est le coeur du plug-in, c'est elle qui sera appelée pour effectuer le traitement.Si le plug-in est un transformeur de texte, alors cette méthode doit renvoyer le texte transformé (le texte d'entrée étant fourni par le paramétre text). Dans les autres cas, la méthode ne doit rien renvoyer (None). Notez qu'il n'est pas interdit de programmer un plug-in qui fasse à la fois transformeur de texte et autre chose.
Le plug-in peut également implémenter une méthode config :
def config(self, trib)
Si elle existe, cette méthode est appelée à la place de process lorsque le plug-in est invoqué depuis le menu. Ceci permet de définir, par exemple, une boîte de dialogue autorisant le réglage de quelques paramètres propres au plug-in. Bien entendu, si le plug-in est appelé autrement que via menu (HotKey/Click, Bot...), c'est la fonction process qui sera exécutée.
Pour clarifier un peu ce qui précède, voici un exemple simple d'un plug-in transformeur de texte. C'est un plopificateur basique, il remplace le texte par "plop".
from plugin import CoinPlugin class coin_plopifier(CoinPlugin): name = "Plopifieur" descr = "Plopifie le texte" def process(self, trib, post, text): return "plop"
Voilà ce qui se passera si ce plug-in est invoqué dans différents contextes :
Alors, c'est faciiiiile hein ? :)
Rien n'interdit dans notre classe coin_plopifier de nous définir des petites méthodes annexes pour améliorer notre plopificateur. Dans le code qui suit, on simule le niveau 1 de plopification de wmcc.
from plugin import CoinPlugin from persistants import CoinStyle from random import choice, randrange import re class coin_plopifier(CoinPlugin): name = "Plopifier" descr = "Traduit le texte en plop meuh de gruiiik limule ka-pika." style = CoinStyle("Style Plop (plugin)", font="Verdana 8 italic", foreground="#a0a0a0") plop_words = [ 'pl0p', 'co1n', 'pika', 'plip', 'zzZz', 'burp', 'meuuh', 'kikoo', 'pouet', 'prout', 'gaaaa', 'moule', 'miaou', 'plooop', 'gnegne', 'gargle', 'blabla', 'limule', 'gloups', 'nartaaa', 'gruiiik', 'blouark', 'fluèèrk', 'ka-pika', 'glouglou', 'kapouééé', 'buarrgll', 'coincoin', 'fmelebele', 'mollusque', 'coccimule', 'pschiittt', 'croucroute', 'piiikachuu', 'bzzoïïnnng', 'rastakouère', 'wolfenstein', 'porteninwak', 'britneycdkey', 'super-tomate', 'eviv-bulgroz', 'obiwan-kenobi', 'bananemagique' ] plop_density = 75 def formap(self, item): res = item if randrange(100) < self.plop_density: res = choice(self.plop_words) return res def process(self, trib, post, text): return " ".join(map(self.formap, text.split()))
Remarques :
L'utilisateur pourrait avoir envie de changer le seuil de plopification, voire de personnaliser sa liste de mots-plops. Plutôt que de passer par une modification du code du plug-in (ce qui nécéciterait en outre de redémarrer pyCoinCoin à chaque changement), on peut doter le plug-in de la méthode config pour autoriser cela. Sachant que la méthode config est appelée lorsque le plug-in est invoqué via le menu de pyCoinCoin, on peut imaginer une boîte de dialogue apparaissant à l'écran et comportant deux champs autorisant l'édition des paramètres plop_density et plop_words.
Pour cela, il faut certes connaître un minimum la programmation avec Tkinter, le module graphique utilisé par pyCoinCoin. Néanmoins, pyCoinCoin fournit des classes de haut niveau rendant ce genre de boîte de dialogue très rapide à ècrire. Considérez le code ci-dessous.
from coinwidgets import * from coindialogs import CoinDialog import tkMessageBox class PlopConfigDialog(CoinDialog): def __init__(self, parent, plop): self.plop = plop CoinDialog.__init__(self, parent, "pyCoinCoin - Configuration plugin Plopifier", [ 'OK', 'Annuler' ], 1) def body(self, master): Label(master, text="Configuration du Plopifier", background="#fcfcda").pack(fill=X, pady=3) self.density = IntField(master, "Densité de la plopification :", value=self.plop.plop_density) self.density.pack(anchor='e', padx=2, pady=3) self.words = TextField(master, "Mots-plops :", value=" ".join(self.plop.plop_words)) self.words.pack(anchor='e', padx=2, pady=3) self.initial_focus = self.density def validate(self): density = self.density.get() if density < 0 or density > 100: tkMessageBox.showwarning("Plopifier", "La densité de plopification doit être un entier entre 0 et 100", parent=self) self.initial_focus = self.density return 0 return 1 def apply(self): self.plop.density = self.density.get() self.plop.words = self.words.get().split()
A présent, il suffit d'ajouter à notre classe coin_plopifier la méthode config comme suit :
def config(self, trib): PlopConfigDialog(trib.root, self)
Voilà un aperçu du résultat :
Quelques remarques sur la class PlopConfigDialog :
Jusqu'ici, nous n'avons étudié que des exemples de plugins transformeurs de textes, c'est-à-dire qui n'agissent que sur le paramètre text de la méthode process. Intéressons-nous à présent aux deux autres paramètres : trib et post.
Le paramètre trib passé à process est de type Tribune. C'est un référence vers le bouchot qui a déclenché le plug-in. Cet objet permet d'accéder depuis le plug-in à virtuellement toutes les fonctions internes de pyCoinCoin. Pour savoir comment l'utiliser proprement (enfin, aussi proprement que la gruikitude intrinsèque du coincoin le permet :)), se référer à la doc de l'API Tribune.
Le paramètre post passé à process est de type Post. Lorsque le plug-in est appelé dans le contexte du Pinnipède (via un HotClick, ou par le PostProcessor ou encore un Bot), post est donc une référence vers le post traité (dans les autres cas -contexte Palmipède, menu-, post sera None).
L'objet Post est défini dans le module baseclasses. Il donne accès aux composantes du post (id, login du posteur, corps du message,...) et comporte des méthodes utiles (comparaison du timestamp avec d'autres posts, obtenir la référence sous la forme hh:mm:ss:n, etc...). Voir la doc de l'API pour tous les détails.