Ir al contenido principal

This is my blog, more about me at marianoguerra.github.io

🦋 @marianoguerra.org 🐘 @marianoguerra@hachyderm.io 🐦 @warianoguerra

de blogger a nikola sin escalas

lo prometido es deuda, acá va una breve descripción de como hice para portar 6 anios de blog en blogger a nikola.

lo primero que hay que hacer es traer el listado de posts de tu blog de blogger, para eso vamos a usar una herramienta de linea de comandos que google provee para interactuar con varios de sus servicios llamada googlecl

después de instalarla corremos:

google blogger list --blog "titulo de tu blog aca" > posts

ahí tenemos un listado de los posts del blog que vamos a usar después.

creamos un directorio donde van a ir los posts y los metadatos:

mkdir htmls

después usamos un script como el siguiente (muy hackoso)

esta escrito en python3 (si, python 3) y usa muchas librerías que facilitan la vida, entre ellas isodate requests y pyquery.

acá esta el código que yo use, no lo usen para evaluar mis habilidades de programador :P

import sys
import csv
import time

from pyquery import PyQuery as pq
import requests

import isodate

POSTS_PATH = sys.argv[1]
print("processing posts from", POSTS_PATH)

with open(POSTS_PATH) as handle:
    reader = csv.reader(handle)

    print("reader", reader)
    for post in reader:
        title, url = post

        if url.startswith("http"):
            print()
            print("processing", title)
            print("fetching", url)

            response = requests.get(url)

            if response.status_code == 200:
                print("got OK response")
                qobj = pq(response.text)

                filename = url.split("/")[-1]
                slug = filename[:-5]

                try:
                    html = qobj(".post-body.entry-content").html()
                    date = qobj("abbr.published").attr("title")
                    dtime = isodate.parse_datetime(date)

                    with open("htmls/" + filename, "w") as html_out:
                        html_out.write(html)

                    with open("htmls/" + slug + ".meta", "w") as meta_out:
                        meta_out.write(title + "\n")
                        meta_out.write(slug + "\n")

                        formatted_date = dtime.strftime("%Y/%m/%d %H:%M")
                        meta_out.write(formatted_date + "\n")

                except Exception as error:
                    print(error)

                time.sleep(2)
            else:
                print("didn't get OK response", response.status_code)

        else:
            print("skipping post", title, "invalid url", url)

lo ponemos en el mismo directorio donde esta el archivo posts y el directorio htmls y corremos:

python3 blogger2nikola.py posts

ahora corremos esto (porque no quiero tocar el código de arriba y no probarlo):

cd htmls
for i in *.html; do mv $i $(basename $i .html).blogger; done

en el conf.py de python, las lineas importantes:

# ...

post_pages = (
    ("posts/*.txt", "posts", "post.tmpl", True),
    ("posts/*.blogger", "posts", "post.tmpl", True),
    ("stories/*.txt", "stories", "story.tmpl", False),
)

# ...

post_compilers = {
    "rest": ('.txt', '.rst'),
    "html": ('.blogger',),
    "markdown": ('.md', '.mdown', '.markdown')
    }

# ...

movemos lo que tenemos en htmls al directorio posts de nuestro blog nikola y le damos arranque:

doit

como final con suspenso, vamos a http://disqus.com/admin/tools/import/platform/blogger/ e iniciamos la migración de comentarios de blogger a disqus (cosa que todavía no termino así que no se si anda)

les dejo el ultimo paso como tarea para la casa, si me acuerdo posteo como me fue con eso.

First (new) Post

First (new) Post

finalmente despues de 6 anios de usar blogger empiezo este proceso de migrar a una infraestructura mas manejable y amena.

porque me voy?

  • porque el editor de blogger apesta

  • es un perno poner codigo y/o texto preformateado

  • porque el editor de blogger apesta

  • porque prefiero no escribir mi blog en un editor WYSIWYG que apesta

  • porque prefiero no tener que terminar escribiendo mis posts a mano en HTML

  • porque prefiero usar mi editor preferido para escribir los posts

  • porque nikola esta buenisimo

  • porque restructuredText esta buenisimo

  • porque nikola esta escrito en python que esta buenisimo

  • porque al usar nikola puedo

    • moverme de hosting (esa excusa que siempre listamos y nunca hacemos)

    • saber que tengo un backup

    • poder manipular los posts con herramientas convencionales[1]

    • probar giladas

    • intentar escribir los posts en N idiomas (para un numero pequenio de N)

ahora empieza un proceso en el que voy a tener una identidad bicefala hasta que encuentre la forma de migrar el contenido de blogger a nikola (lindo proyecto para agregar a la lista de proyectos abandonados)

porque me demore?

tenia la ilusion de hacer algo similar a nikola como excusa para usar redo [2]

[1] convencionales para nionios [2] https://github.com/apenwarr/redo/

lst - automatizando la adiccion a tener listas de cosas

lst - manage lists in files

I keep lot of lists, usually I edit them with vim, this will end... today.
lst is a small program that provides functionality to manipulate lists of things.

https://github.com/marianoguerra/lst/

general help

usage: lst [-h] {add,remove,purge,slice,head,tail,filter,export} ...

positional arguments:
{add,remove,purge,slice,head,tail,filter,export}
add add an element to a list
remove remove element from list
purge purge removed items from the file
slice show a slice of the list
head show the first N elements of the list
tail show the last N elements of the list
filter show elements that match the filter

optional arguments:
-h, --help show this help message and exit

add command

usage: lst add [-h] [-a | -i INDEX] [-t TAG [TAG ...]] LIST MSG [MSG ...]

positional arguments:
LIST
MSG

optional arguments:
-h, --help show this help message and exit
-t TAG [TAG ...], --tags TAG [TAG ...]
tag message with specified tag

examples

# add item with tags

$ ~ lst add todos do something interesting -t tag1 tag2 tag3
* Tue Jul 10 17:55:46 2012 do something interesting # tag1 tag2 tag3

# add item without tags

$ ~ lst add todos do something else
* Tue Jul 10 17:55:55 2012 do something else

remove command

usage: lst remove [-h] [-a | -i INDEX [INDEX ...]] [-f] LIST

positional arguments:
LIST

optional arguments:
-h, --help show this help message and exit
-a, --all remove all elements from list
-i INDEX [INDEX ...], --index INDEX [INDEX ...]
remove elements at index
-f, --force don't ask for confirmation

examples

# example items from a list

0 * Tue Jul 10 17:55:46 2012 do something interesting # tag1 tag2 tag3
1 * Tue Jul 10 17:55:55 2012 do something else
2 * Tue Jul 10 17:59:20 2012 conquer the world
3 * Tue Jul 10 17:59:28 2012 do this demo # recursive

# remove the item at index 1

$ ~ lst remove todos -i 1

# result

0 * Tue Jul 10 17:55:46 2012 do something interesting # tag1 tag2 tag3
1 x Tue Jul 10 17:55:55 2012 do something else
2 * Tue Jul 10 17:59:20 2012 conquer the world
3 * Tue Jul 10 17:59:28 2012 do this demo # recursive

# remove items at index 0 and 3
$ ~ lst remove todos -i 0 3

# result

0 x Tue Jul 10 17:55:46 2012 do something interesting # tag1 tag2 tag3
1 x Tue Jul 10 17:55:55 2012 do something else
2 * Tue Jul 10 17:59:20 2012 conquer the world
3 x Tue Jul 10 17:59:28 2012 do this demo # recursive

purge command

usage: lst purge [-h] [-f] LIST

positional arguments:
LIST

optional arguments:
-h, --help show this help message and exit
-f, --force don't ask for confirmation

examples

# example items from a list

0 x Tue Jul 10 17:55:46 2012 do something interesting # tag1 tag2 tag3
1 x Tue Jul 10 17:55:55 2012 do something else
2 * Tue Jul 10 17:59:20 2012 conquer the world
3 x Tue Jul 10 17:59:28 2012 do this demo # recursive

$ ~ lst purge todos
are you sure you want to purge the list? [yes/no] yes

# result (removed items are completely removed from the list)

0 * Tue Jul 10 17:59:20 2012 conquer the world

slice command

usage: lst slice [-h] [-a] [-i] LIST BEGIN END STEP

positional arguments:
LIST
BEGIN
END
STEP

optional arguments:
-h, --help show this help message and exit
-a, --show-all show removed elements too
-i, --show-index show the absolute index of the item

examples

# slice from 0 to 2 with step 1

$ ~ lst slice todos 0 2 1
* Tue Jul 10 17:59:20 2012 conquer the world
* Tue Jul 10 18:02:16 2012 do thing 1

# same as before but displaying index

$ ~ lst slice todos 0 2 1 -i
0 * Tue Jul 10 17:59:20 2012 conquer the world
1 * Tue Jul 10 18:02:16 2012 do thing 1

# slice from 0 to 4 with step 2 showing index

$ ~ lst slice todos 0 4 2 -i
0 * Tue Jul 10 17:59:20 2012 conquer the world
2 * Tue Jul 10 18:02:16 2012 do thing 1

# slice from 0 to 4 with step 1 showing index

$ ~ lst slice todos 0 4 1 -i
0 * Tue Jul 10 17:59:20 2012 conquer the world
1 * Tue Jul 10 18:02:16 2012 do thing 1
3 * Tue Jul 10 18:02:28 2012 do thing 3 # tag task3

# slice from 0 to 4 with step 1 showing index and removed items

$ ~ lst slice todos 0 4 1 -i -a
0 * Tue Jul 10 17:59:20 2012 conquer the world
1 * Tue Jul 10 18:02:16 2012 do thing 1
2 x Tue Jul 10 18:02:19 2012 do thing 2 # tag
3 * Tue Jul 10 18:02:28 2012 do thing 3 # tag task3

head command

usage: lst head [-h] [-a] [-i] [-c COUNT] LIST

positional arguments:
LIST

optional arguments:
-h, --help show this help message and exit
-a, --show-all show removed elements too
-i, --show-index show the absolute index of the item
-c COUNT, --count COUNT

examples

# list first items with default count (10)

$ ~ lst head todos
* Tue Jul 10 17:59:20 2012 conquer the world
* Tue Jul 10 18:02:16 2012 do thing 1
* Tue Jul 10 18:02:19 2012 do thing 2 # tag
* Tue Jul 10 18:02:28 2012 do thing 3 # tag task3
* Tue Jul 10 18:02:35 2012 do thing 4 # task task4
* Tue Jul 10 18:02:43 2012 do thing 5 # task

# list first two

$ ~ lst head todos -c 2
* Tue Jul 10 17:59:20 2012 conquer the world
* Tue Jul 10 18:02:16 2012 do thing 1

# list first 4 with index

$ ~ lst head todos -c 4 -i
0 * Tue Jul 10 17:59:20 2012 conquer the world
1 * Tue Jul 10 18:02:16 2012 do thing 1
2 * Tue Jul 10 18:02:19 2012 do thing 2 # tag
3 * Tue Jul 10 18:02:28 2012 do thing 3 # tag task3

# remove one

$ ~ lst remove todos -i 2

# list again (see that item at index 2 is missing)

$ ~ lst head todos -i
0 * Tue Jul 10 17:59:20 2012 conquer the world
1 * Tue Jul 10 18:02:16 2012 do thing 1
3 * Tue Jul 10 18:02:28 2012 do thing 3 # tag task3
4 * Tue Jul 10 18:02:35 2012 do thing 4 # task task4
5 * Tue Jul 10 18:02:43 2012 do thing 5 # task

# list all (see that item at index 2 is marked as removed)

$ ~ lst head todos -i -a
0 * Tue Jul 10 17:59:20 2012 conquer the world
1 * Tue Jul 10 18:02:16 2012 do thing 1
2 x Tue Jul 10 18:02:19 2012 do thing 2 # tag
3 * Tue Jul 10 18:02:28 2012 do thing 3 # tag task3
4 * Tue Jul 10 18:02:35 2012 do thing 4 # task task4
5 * Tue Jul 10 18:02:43 2012 do thing 5 # task

tail command

usage: lst tail [-h] [-a] [-i] [-c COUNT] LIST

positional arguments:
LIST

optional arguments:
-h, --help show this help message and exit
-a, --show-all show removed elements too
-i, --show-index show the absolute index of the item
-c COUNT, --count COUNT

examples

# list last items with default count (10)

$ ~ lst tail todos
* Tue Jul 10 17:59:20 2012 conquer the world
* Tue Jul 10 18:02:16 2012 do thing 1
* Tue Jul 10 18:02:28 2012 do thing 3 # tag task3
* Tue Jul 10 18:02:35 2012 do thing 4 # task task4
* Tue Jul 10 18:02:43 2012 do thing 5 # task

# list last two

$ ~ lst tail todos -c 2
* Tue Jul 10 18:02:35 2012 do thing 4 # task task4
* Tue Jul 10 18:02:43 2012 do thing 5 # task

# list last 4 with index

$ ~ lst tail todos -c 4 -i
1 * Tue Jul 10 18:02:16 2012 do thing 1
3 * Tue Jul 10 18:02:28 2012 do thing 3 # tag task3
4 * Tue Jul 10 18:02:35 2012 do thing 4 # task task4
5 * Tue Jul 10 18:02:43 2012 do thing 5 # task

# list all (see that item at index 2 is marked as removed)

$ ~ lst tail todos -c 4 -i -a
2 x Tue Jul 10 18:02:19 2012 do thing 2 # tag
3 * Tue Jul 10 18:02:28 2012 do thing 3 # tag task3
4 * Tue Jul 10 18:02:35 2012 do thing 4 # task task4
5 * Tue Jul 10 18:02:43 2012 do thing 5 # task

filter command

usage: lst filter [-h] [-a] [-i] [-t TAG [TAG ...] | -T TAG [TAG ...]]
LIST [QUERY [QUERY ...]]

positional arguments:
LIST
QUERY

optional arguments:
-h, --help show this help message and exit
-a, --show-all show removed elements too
-i, --show-index show the absolute index of the item
-t TAG [TAG ...], --tags TAG [TAG ...]
show elements that have *any* of the tags
-T TAG [TAG ...], --all-tags TAG [TAG ...]
show elements that have *all* of the tags

examples

# apply no filter

$ ~ lst filter todos
* Tue Jul 10 17:59:20 2012 conquer the world
* Tue Jul 10 18:02:16 2012 do thing 1
* Tue Jul 10 18:02:28 2012 do thing 3 # tag task3
* Tue Jul 10 18:02:35 2012 do thing 4 # task task4
* Tue Jul 10 18:02:43 2012 do thing 5 # task

# list items that contain the word "thing"

$ ~ lst filter todos thing
* Tue Jul 10 18:02:16 2012 do thing 1
* Tue Jul 10 18:02:28 2012 do thing 3 # tag task3
* Tue Jul 10 18:02:35 2012 do thing 4 # task task4
* Tue Jul 10 18:02:43 2012 do thing 5 # task

# list items that contain the word "thing" or the tag "task"

$ ~ lst filter todos thing -t task
* Tue Jul 10 18:02:16 2012 do thing 1
* Tue Jul 10 18:02:28 2012 do thing 3 # tag task3
* Tue Jul 10 18:02:35 2012 do thing 4 # task task4
* Tue Jul 10 18:02:35 2012 do thing 4 # task task4
* Tue Jul 10 18:02:43 2012 do thing 5 # task
* Tue Jul 10 18:02:43 2012 do thing 5 # task

# list items that contain the tag "task"

$ ~ lst filter todos -t task
* Tue Jul 10 18:02:35 2012 do thing 4 # task task4
* Tue Jul 10 18:02:43 2012 do thing 5 # task

# list items that contain the tag "task" or "tag"

$ ~ lst filter todos -t task tag
* Tue Jul 10 18:02:28 2012 do thing 3 # tag task3
* Tue Jul 10 18:02:35 2012 do thing 4 # task task4
* Tue Jul 10 18:02:43 2012 do thing 5 # task

# list items that contain the tag "task" and "tag"

$ ~ lst filter todos -T task tag

# list items that contain the tag "task" and "task4"

$ ~ lst filter todos -T task task4
* Tue Jul 10 18:02:35 2012 do thing 4 # task task4

# list items that contain the tag "task" or "task4"

$ ~ lst filter todos -t task task4
* Tue Jul 10 18:02:35 2012 do thing 4 # task task4
* Tue Jul 10 18:02:43 2012 do thing 5 # task

# list items that contain the word "world"

$ ~ lst filter todos world
* Tue Jul 10 17:59:20 2012 conquer the world

configuration

by default the configuration is looked up in .config/lst
the file contains a JSON object with the configuration of the program with the following subojects:

lists

the lists object contains as keys the names of the lists that you want to configure and as values the configuration for those lists, for example:
if the path to a list doesn't exists it's created:
{
"lists": {
"links": {
"format": "src/me/links/%Y/%m.links" // strftime format can be used
}
}
}

fields

format
is the path to the list, you can use ~ to refer to the user's home and any format from datetime.strftime

details

license

MIT + optional beer for the author

author

marianoguerra

tools

python 3

releases! una unica pagina para seguir las releases de todas tus librerias por web, atom o rss

se me ocurrió ayer (mejor dicho lo necesite ayer), no lo encontré y lo hice.

básicamente es un script que periodicamente chequea en los proyectos de una lista* las versiones y si se actualizaron las agrega a una lista y genera un feed atom y rss, tambien provee una pagina web para ver los ultimos 100 updates, con links y posibilidad de ver detalles y comentar en cada release individual.

todo sin backend, solo generacion de archivos estaticos y javascript en el cliente.

la pagina esta acá: releases!

si querés que agregue alguna librería avisame por algún lado.

* proyectos que tienen un archivo package.json

ya migraste tu modulo a python 3? (aka migrando feedformatter a python 3)

resulta que ayer me puse a hacer una cosa que me hacia falta pero no era "critica" así que decidí hacerla en python3, supuse que a esta altura todo iba a estar mejor, pero me encontré con el primer escollo al buscar un modulo para generar un feed atom ya que feedformatter no anda en python 3.

en lugar de quejarme y volver al querido python 2, me puse un par de horas y lo migre a python 3 y viendo que no era muy difícil hice que el mismo modulo ande para python >= 2.5 (no se si anda en python 2.4 porque no tengo uno a mano)

los invito a mirarlo/probarlo/ayudarme en https://github.com/marianoguerra/feedformatter/

el modulo es bastante simple (y no muy lindamente programado) pero me hacia falta y no estaba.

así que los invito a hacer algo parecido, esta bueno para ejercitar, contribuir algo de vuelta y ayudar a que la gente considere python 3 mas seguido.

ahora lo que me falta es ver si puedo subir el cambio a pypi, no se como se hace y dado que el proyecto no tiene tests no se si rompi algo (mas que probar lo simple), pero bue, es lo que hay.

como me podes ayudar?

 * probalo si usaste feedformatter
 * bajalo y probalo y fijate si se rompe
 * escribí una pequenia guia de uso al estilo pymtw[1] (y avisame)
 * agregale unittests!

[1] http://www.doughellmann.com/PyMOTW/py-modindex.html

Sobre criticar


In many ways, the work of a critic is easy. We risk very little yet enjoy a position over those who offer up their work and their selves to our judgment. We thrive on negative criticism, which is fun to write and to read.
But the bitter truth we critics must face, is that in the grand scheme of things, the average piece of junk is probably more meaningful than our criticism designating it so.
But there are times when a critic truly risks something, and that is in the discovery and defense of the new.
The world is often unkind to new talent, new creations, the new needs friends


la fuente es la pelicula ratatouille, la cual no vi pero vi el quote por ahi.

camino a nantes, motorhome, camping, castillos y casamiento

una argentina de los pagos de Florencio Varela conoce a un francés de un pueblo cercano a Nantes ...fast forward... y se casan (no es una biografía de la pareja).


en el medio me conocen por aleatoriedades influenciadas por la agencia de intercambio alemana, lo que motiva por razones desconocidas la invitación de este indigno ser a su casamiento.

la ubicación se establece en un pueblo cercano al origen del futuro esposo, razón por la cual se organizan los amigos provenientes de Stuttgart para cruzar Francia de este a oeste, y aprovechando dicho evento, conocer lugares intermedios.

al protagonista y escritor de este post le toca viajar en una combi totalmente acondicionada para este tipo de actividades con la compañia de su novia y 3 amigos.

el viaje comienza un jueves a bajas horas de la mañana como resultado de una reorganización de ultimo momento por causas desconocidas.

...acá pasan cosas que el autor desconoce ya que durmió como morsa las primeras horas del viaje...

a mitad de camino (y mitad de Francia) comienza una región que se caracteriza por su alta concentración de castillos, razón por la cual aprovechamos para visitar aquellos que no requieran el pago de entrada o que realmente lo justifiquen.

luego de pasear y sacar fotos nos dedicamos a buscar un camping y aprovisionarnos de elementos para realizar, dados los limitados recursos, algo así como un asado.

luego del mismo nos retiramos a descansar para comenzar el día siguiente con visitas a castillos y continuando hacia Nantes.


allí nos hospedamos en algo llamado gite que es algo así como una casa de campo grande que alquila habitaciones.



superadas las limitaciones comunicacionales nos establecemos y desayunamos exitosamente para luego ir hacia el casamiento a realizarse en la cuna del vino Muscadet donde ingerimos cantidades industriales de comida y vino para luego festejar e irnos a dormir.


al día siguiente temprano emprendimos un regreso acelerado debido a la necesidad de algunos de los personajes de esta historia de volver a trabajar al día siguiente.

fin.

sorprende a tus amigos, se el alma de la fiesta, vos tambien podes ser un chico rfc!

se te acabaron las conversaciones en una fiesta?

querés impresionar a tus amigos con tus conocimientos detallados de cuando usar "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",    "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY" y "OPTIONAL"?

querés interrumpir a alguien para decirle "well actually" y demostrarle que vos sabes mas de algo que el?

entonces este post es para vos!

ya no tenes que googlear un RFC o leerlo online, la  solucion esta a un apt-get de distacia!


sudo apt-get install doc-rfc{,-experimental,-informational,-misc,-old-std,-others,-std,-std-proposed} xml2rfc

y a leer!

zmore /usr/share/doc/RFC/informational/rfc2324.txt.gz

si la razón de todo esto es leer un rfc que esta en xml (porque todo lo que un humano lee y edita tiene que estar en xml, porque es fácil para los humanos, hagamos las cosas fáciles para las computadoras y difíciles para los humanos) entonces:

xml2rfc draft-zyp-json-schema-04.xml

y despues de verlo fallar con el error:

ml2rfc: error: I can't synthesize a date in 2010 around input line 24
key not known
while executing
"::${basename}::pkgconfig get scriptdir,runtime"

y pelear y googlear, cambio la linea por:

 <date year="2012" month="June" day="14"/>

y anda. ahora a leer el bendito rfc.

para evitar que la gran audiencia de este blog (?) vaya a lanata a decir "queremos preguntar", aca un corto FAQ:

porque demonios? 

porque estoy haciendo un proyecto y quiero estar al dia con la ultima version del draft que va a salir "pronto".

que odias ademas de xml? 

la pagina de edición de posts de blogger.

vim: mejor indentacion para javascript

me estaba cansando que en algunos casos vim no me indentaba automáticamente el código, tendía a ser si estaba adentro de un json literal o algo así.

leyendo un poco me entere que es porque por defecto vim usa el indentador de C para javascript y cuando ve cosas que no entiende hace lo que todos hariamos:



busque un poco y encontre este plugin:

https://github.com/pangloss/vim-javascript

que promete no solo indentar javascript en archivos .js sino dentro del html, para ello lo instale con pathogen:

cd ~/.vim/bundle
git clone https://github.com/pangloss/vim-javascript.git

y como todo usuario atolondrado pegue lo que vi mas abajo en mi .vimrc

let g:html_indent_inctags = "html,body,head,tbody"
let g:html_indent_script1 = "inc"
let g:html_indent_style1 = "inc"

ahora vamos a ver como anda, por lo pronto me indenta bien en el html cosa que es muy util (aunque uno nunca deberia escribir js en html :)

edit:

  despues de usarlo un poco me di cuenta que no me estaba indentando igual en html y en archivos .js me fui a leer y me di con que hay que correr rake install en el directorio despues de traerlo para que instale la sintaxis y el indentador:

sudo apt-get install rake
cd ~/.vim/bundle/vim-javascript
rake install