Spanish only, since it's about a video in spanish ;-)
Acá está, gracias a la gente de Junín, un video de mi charla "Aplicaciones extensibles usando PyQt", en la que intento mostrar como desarrollar una aplicación con PyQt y yapsy.
No es una charla con la que esté muy contento. La otra salió mejor, pero no se filmó, así que quedará solo en la memoria de los cuatro gatos locos que estábamos ahí ;-)
Una manera (si estás programando en Python) es usar Yapsy..
Yapsy es asombroso. También, carece completamente de documentación
entendible. Veamos si este post arregla un poco esa parte y deja
sólo lo asombroso.
Update: No había visto la documentación nueva de Yapsy. Es mucho mejor que la que había antes :-)
Esta es la idea general con yapsy:
Creás un Plugin Manager que puede encontrar y cargar plugins de una
lista de lugares (por ejemplo, de ["/usr/share/appname/plugins",
"~/.appname/plugins"]).
Una categoría de plugins es una clase.
Hay un mapeo entre nombres de categoría y clases de categoría.
Un plugin es un módulo y un archivo de metadata. El módulo define
una clase que hereda de una clase de categoría, y pertenece a
esa categoría.
El archivo de metadata tiene cosas como el nombre del plugin,
la descripción, la URL, versión, etc.
Una de las mejores cosas de Yapsy es que no especifica demasiado.
Un plugin va a ser simplemente un objeto Python, podés poner lo que
quieras ahí, o lo podés limitar definiendo la intefaz en la clase
de categoría.
De hecho, lo que vengo haciendo con las clases de categoría es:
Arranco con una clase vacía
Implemento dos plugins de esa categoría
Los pedazos en común los muevo dentro de la categoría.
Pero créanme, esto va a ser mucho más claro con un ejemplo :-)
Lo voy a hacer con una aplicación gráfica en PyQt, pero Yapsy funciona
igual de bien para aplicaciones "headless" o para líneas de comando.
Comencemos con algo simple: un editor HTML con un widget preview.
Este es el código de la aplicación, que es realmente simple (no puede guardar
archivos ni nada interesante, es sólo un ejemplo):
Pero esta aplicación tiene un obvio límite: hay que escribir HTML! Por qué no
escribir python y que lo muestre resaltado en HTML? O markup de Wiki! O reStructured
text!
Uno podría, en principio, implementar todos esos modos, pero estás asumiendo
la responsabilidad de soportar cada cosa-que-se-convierte-en-HTML. Tu aplicación
sería un monolito. Ahí entra Yapsy.
Creemos entonces una categoría de plugins, llamada "Formatter" que toma texto plano
y devuelve HTML. Después agreguemos cosas en la UI para que el usuario pueda elegir
que formatter usar, e implementemos un par.
Esta es la clase de categoría de plugins:
Por supuesto que no sirve de nada sin plugins! Asi que creemos un par.
Primero, un plugin qye toma código python y devuelve HTML, usando pygments.
Como ven, eso va en una carpeta plugins. Después le decimos a Yapsy que
busque los plugins ahi adentro.
Para ser reconocido como un plugin, necesita metadata:
Y realmente, eso es todo lo que hay que hacer para hacer un plugin. Acá
hay otro para comparar, que usa docutils para formatear reStructured Text:
Y acá están en acción:
Of course using categories you can do things like a "Tools" category, where the
plugins get added to a Tools menu, too.
Este es el código del lado de la aplicación:
Resumiendo: es fácil, y te lleva a mejorar la estructura interna de tu aplicación
y terminás con mejor código.
Y... este no lo estoy haciendo solo, lo que lo hace más divertido.
Es un administrador de eBooks (o de libros en general?) que te ayuda a tener tus PDF/Mobi/FB2/loquesea organizados, y debería
eventualmente sincronizarlos con el dispositivo que querés usar para leerlos.
Podés bajar libros de FeedBooks. Esos libros se descargan, se agregan a la base de datos, se etiquetan, se baja la tapa, etc. etc.
Podés importar tu carpeta actual de libros en bulto
Aranduka usa google y otros servicios para tratar de
adivinar (por los nombres) qué libro es ese y llenar
los datos extra.
Podés "adivinar" esos datos extra
Marcando como confiables algunos datos (por ejemplo,
el título) Aranduka busca candidatos que coincidan y
elegís el correcto.
Por supuesto que también se puede editar los datos
manualmente.
Y eso es todo por ahora. Features planeados:
Muchos como para hacer una lista.
La meta es clara:
Debe ser hermoso (y no lo es)
Debe ser potente (y todavía no)
Debe ser mejor que la "competencia"
Si no se logran esas tres metas, es un fracaso. Tal vez sea un fracaso divertido, pero igual es fracasar.
Sí, eso es todo, tenés una linda barra de progreso ASCII que cruza la terminal, soporta que la cambies de tamaño y se mueve mientras iterás de 0 a 79.
El módulo progressbar incluso tiene cosas mejores como ETA o velocidades de transferencia, y todo es así de fácil.
¿Ese código... no está bueno? ¿Querés una barra de progreso para ese loop? ¡Lo "envolvés" y listo! Y por supuesto, como yo programo con PyQt, quiero que PyQt tenga algo igual de bueno.
Así se ve el resultado:
Esto lo podés hacer con cualquier toolkit, y probablemente deberías. Tiene un feature extra: podés interrumpir la iteración, y este es el (poco) código:
# -*- coding: utf-8 -*-importsys,timefromPyQt4importQtCore,QtGuidefprogress(data,*args):it=iter(data)widget=QtGui.QProgressDialog(*args+(0,it.__length_hint__()))c=0forvinit:QtCore.QCoreApplication.instance().processEvents()ifwidget.wasCanceled():raiseStopIterationc+=1widget.setValue(c)yield(v)if__name__=="__main__":app=QtGui.QApplication(sys.argv)# Do something slowforxinprogress(xrange(50),"Show Progress","Stop the madness!"):time.sleep(.2)