Volpe's Blog

Opiniones, viajes y código

Programación

en Programación

Bloguear como un nerd: Cloudflare Pages es todo lo que necesitás

Bloguear como un nerd: Cloudflare Pages es todo lo que necesitás

Me tomó 9 años volver a bloguear, y usé mantener el viejo WordPress como excusa todo ese tiempo. Resulta que la solución era gratis. La versión anterior era un WordPress corriendo en un VPS en Digital Ocean. En teoría, podría haber empezado a escribir ahí nomás y darle publicar. Pero la versión de WordPress se iba desactualizando cada vez más y los plugins que usaba también se iban deprecando, así que iba a tener que migrar. El blog se caía cada un par de años por problemas en el VPS.

Más allá de los dolores de cabeza operativos, había problemas más profundos. Una de las funcionalidades clave que quería tener era soporte multilenguaje, y eso no está disponible de fábrica en WordPress. Cambiar el plugin implicaría asegurarme de mantener las URLs iguales y migrar todos los datos al nuevo. Además, necesitaba asegurarme de que funcionara y de no ser hackeado, algo que le pasó a WordPress muchas veces. El setup con el VPS requería mantenimiento, y lo había armado cuando recién estaba empezando en software, así que probablemente habría tenido que reconstruirlo desde cero. Si alguno de mis posts pegaba, probablemente me caía o tenía performance muy degradada. También hay preocupaciones serias que todos deberían tener sobre WordPress (el meltdown de Matt).

Alternativas al self-hosting

Por supuesto, existen los WordPress con un clic, pero eso implica pagar mensualmente y arriesgarme a que se vuelva caro de un día para el otro si un post tiene mucho tráfico. Migrar tampoco sería trivial si quería que mi viejo blog mantuviera la misma estructura y, más importante, las URLs. También podría alojar en algo como Substack o plataformas similares, pero eso significaría no tener control total de mi sitio. No tengo nada contra Substack, hasta tengo algunas acciones, pero prefiero tener control total de mi rincón en internet, donde puedo escribir lo que quiera sin que me baneen o demonicen. No quiero que ningún incentivo externo influya en lo que escribo.

También pensé en usar IA para crear un blog a medida y hostearlo en algo como Vercel, pero eso se sentía más como un proyecto de pasión que como algo que me facilitaría la vida.

Continuar leyendo →
en Programación, PyGTK, Python, Twisted

Twisted + PyGTK

Hace unas semanas empece a interesarme en Twisted y en programacion asincronica en general. La verdad es que encuentro muy amigable la forma en la que Twisted maneja los callbacks y los eventos.

He estado trabajando en un programa con una interfaz grafica hecha con Pygtk que usa un thread para cada tarea y me pregunte si es posible tener ese mismo programa corriendo en un solo thread asincronicamente. Es verdaderamente simple implementar codigo twisted en aplicaciones escritas en PyGtk, los dos son basados en eventos y Twisted tiene una API nativa para ese objetivo.

Empecemos con un ejemplo simple de PyGTK:

import gtk

class Gui:
    def __init__(self):
        self.window = gtk.Window()
        self.window.set_default_size(200,200)
        self.window.set_title("Simple PyGTK program")

        self.vbox = gtk.VBox()

        self.button = gtk.Button("I'm a button!")
        self.label = gtk.Label("Nothing here")

        self.vbox.pack_start(self.button)
        self.vbox.pack_start(self.label)

        self.window.add(self.vbox)

        self.button.connect("clicked", self.on_clicked)
        self.window.connect("destroy", lambda x: gtk.main_quit())
        self.window.show_all()
        self.window.show()

    def on_clicked(self, widget):
       self.label.set_text("You clicked the button!") 

if __name__ == "__main__":
    app = Gui()
    #Empezamos el bucle de GTK
    gtk.main()

Este ejemplo usa el bucle de Gtk. Una aplicacion hecha en Twisted usa el Twisted reactor, por lo tanto, necesitamos que el reactor “entienda” las señales emitidas por GTK

from twisted.internet import gtk2reactor # for gtk-2.0
gtk2reactor.install()

#Tu código
#...

from twisted.internet import reactor
#this starts the reactor
reactor.run()

Ahora podemos reimplementar nuestro primer ejemplo y sería algo parecido a esto: Now we can re-implement or first example and it would look like this

import gtk
from twisted.internet import gtk2reactor # for gtk-2.0
gtk2reactor.install() #Instalamos de gtk2 reactor
#NOTE: This have to be at top always, before starting the reactor
#NOTA: Esto tiene que estar siempre al principio, antes de importar el reactor

class Gui:
    def __init__(self):
        self.window = gtk.Window()
        self.window.set_default_size(200,200)
        self.window.set_title("Simple PyGTK program")

        self.vbox = gtk.VBox()

        self.button = gtk.Button("I'm a button!")
        self.label = gtk.Label("Nothing here")

        self.vbox.pack_start(self.button)
        self.vbox.pack_start(self.label)

        self.window.add(self.vbox)

        self.button.connect("clicked", self.on_clicked)
        self.window.connect("destroy", lambda x: gtk.main_quit())
        self.window.show_all()
        self.window.show()

    def on_clicked(self, widget):
       self.label.set_text("You clicked the button!") 

if __name__ == "__main__":
    app = Gui()
    #Basta de GTK!
    #gtk.main()
    from twisted.internet import reactor
    #Empezamos el loop
    reactor.run()

Ahora podemos felizmente disfrutar el poder de Twisted en nuestras aplicaciones graficas :) . Para terminar, este es un simple ejemplo de callbacks al estilo Twisted

import gtk
from twisted.internet import gtk2reactor # for gtk-2.0
gtk2reactor.install() #Instalamos de gtk2 reactor
#NOTE: This have to be at top always, before starting the reactor
#NOTA: Esto tiene que estar siempre al principio, antes de importar el reactor

class Gui:
    def __init__(self):
        self.window = gtk.Window()
        self.window.set_default_size(200,200)
        self.window.set_title("Simple PyGTK program")

        self.vbox = gtk.VBox()

        self.button = gtk.Button("I'm a button!")

        self.time = time.time()

        self.label = gtk.Label("0")

        self.vbox.pack_start(self.button)
        self.vbox.pack_start(self.label)

        self.window.add(self.vbox)

        self.button.connect("clicked", self.on_clicked)
        self.window.connect("destroy", lambda x: gtk.main_quit())
        self.window.show_all()
        self.window.show()
        self.time = time.time()

    def on_clicked(self, widget=None):
        self.label_text = time.time() - self.time
        self.label.set_text("%.2fs" % self.label_text)
        #Twisted va a llamar a la funcion self.on_clicked cada 100ms
        reactor.callLater(.1, self.on_clicked)

if __name__ == "__main__":
    app = Gui()
    #Basta de GTK!
    #gtk.main()
    from twisted.internet import reactor
    #Empezamos el loop
    reactor.run()

Twisted tiene otras APIS para otros toolkits como Tkinter, wxPython, Win32(Windows) y PyUI. Para mas info consultar la documentación oficial.

Continuar leyendo →