jueves, julio 03, 2014

PostgreSQL y trabajo en equipo

Quiero que las tablas que crea un usuario puedan ser manipuladas por un grupo de usuarios. Pensé que todo sería tan sencillo como definir un grupo de usuarios y registrar a los usuarios en él, pero nada más lejos de la verdad.

PostgreSQL 9.2


Primero pensé que GRANT <privileges> ON ALL TABLES ON SCHEMA <schema> TO <ROLE> haría la magia si <ROLE> es el grupo.

En cierta manera sí lo hace, pero sólo modifica las tablas existentes. Para las tablas que se crearán a futuro, habría que repetir estos pasos nuevamente.

Una solución permanente es definir los privilegios por defecto de la base de datos. Esto se logra con: ALTER DEFAULT PRIVILEGES GRANT <privileges> ON TABLES TO <ROLE>. Si <ROLE> es el grupo, funciona. Pero, hay un detalle: sólo tiene efecto para el usuario que ejecuta el comando. Es decir, sólo las tablas que él crea obtendrán cederán los privilegios al grupo.

ALTER DEFAULT PRIVILEGES permite definir un rol al que pertenezca quien ejecute el comando, para que se modifiquen las tablas que ese rol cree con los privilegios por defecto. Para definir ese rol se indica después de ALTER DEFAULT PRIVILEGES la frase FOR ROLE <ROLE>.

Así que la solución podría haber sido:

ALTER DEFAULT PRIVILEGES FOR ROLE <ROLE> GRANT <privileges> ON TABLES TO <ROLE>;

Haciendo que ROLE sea el grupo. De esta manera, cuando un miembro del grupo cree una tabla, concederá los privilegios definidos.

Pero no. No funciona, ya lo probé. Lamentablemente habrá que repetir el ALTER DEFAULT PRIVILEGES por cada rol del grupo; y estar pendiente de ejecutar este comando cada vez que se registre un nuevo usuario al grupo y revocar los privilegios por defecto cuando el usuario deje de pertenecer al grupo.

De cómo utilicé udev para fijar unos parámetros en una cámara web "Creative vf0070"

Al conectar la cámara web en la computadora, las imágenes que se reproducían en la pantalla se veían muy mal[1]: con mucho brillo y no se podían entender bien.
[1] Utilicé el programa Cheese para poder observar las imágenes.


El programa Cheese tiene unos controles que permiten modificar distintos valores de las imágenes con los que se puede intentar corregir los defectos. Estos controles se alcanzan en las preferencias de la aplicación, en una sección llamada "Imagen". Sin embargo, en mi caso no pude corregir las imágenes con estos controles.


La razón es que estos controles realizan un proceso posterior a la captura de las imágenes y los defectos que tenían las que estaba viendo se debían, supongo, a problemas que sucedían al momento de capturar las imágenes. Es decir, estos controles permiten "editar" las imágenes ya capturadas, como si de una herramienta de edición de imágenes se tratase (como Gimp o PhotoShop). Sin embargo, debía corregir la captura misma de las imágenes para poder apreciar bien las mismas.

Para realizar las correcciones de captura mencionadas, utilicé un programa llamado Video4Linux Control Panel. Para instalarlo, ejecuté el siguiente comando:

$ sudo apt install v4l2ucp

Este programa es unas simple herramienta que te presenta en una interfaz gráfica unos controles que te permiten modificar los parámetros de captura de imágenes de la cámara web.

En mi caso corregí las imágenes modificando el valor de exposición (Exposure) y ganancia (Gain), que son parámetros establecidos en la cámara misma, y también modifiqué el parámetro Gamma y el balance de blancos (White valance), que según indica la aplicación, son parámetros a nivel del software (ver la captura de pantalla). Estas modificaciones las hacía mientras veía los efectos en las imágenes reproducidas por Cheese.


El asunto parecía resuelto hasta que desconecté y conecté de nuevo la cámara. Obtuve el siguiente resultado:


Si comparan los parámetros de las últimas dos capturas de pantalla, pueden observar que los valores etiquetados como "software" permanecieron iguales, pero que la exposición (Exposure) y la ganancia (Gain) cambiaron. Aún más, al observar la última y antepenúltima captura de pantalla, pueden ver que los valores de exposición y ganancia son iguales.

Este fenómeno se repetía una y otra vez cada vez que apagaba la computadora o cambiaba la cámara de una computadora a otra (en cuyo caso, todos los valores se perdían y se establecían a los que observan en la antepenúltima captura de pantalla).

¿Por qué pasa esto?. No lo se. Pero sospecho que los valores que no dicen "software" son valores almacenados directamente en la cámara web, y esta tal vez no esté diseñada con una memoria persistente.

En todo caso, mi interés era que los valores que se establecieran una vez fueran permanentes.

udev al rescate

Al programa Video4Linux Control Panel lo acompaña una pequeña herramienta llamada v4l2ctrl. Este programa permite guardar en un archivo los valores de los parámetros establecidos de la cámara para poder restablecerlos en un momento futuro.

Así, para guardar esos valores, se ejecuta el siguiente comando:

$ v4l2ctrl -s valores

De esta manera, los valores que está utilizando en el momento de ejecutar el comando, son guardados en el archivo "valores".

Entonces, cuando se desee en otro momento establecer esos valores a la cámara, basta con utilizar el mismo comando de la siguiente forma:

$ v4l2ctrl -l valores

La diferencia es la opción -l (del inglés "load" o "cargar")en vez de la opción -s (del inglés "save" o "guardar").

Claro, estar "cargando" la configuración que queremos fijar de manera permanente, cada vez que iniciemos la computadora o cada vez que conectemos la cámara es una situación indeseable.

Lo que hice para lograr el efecto de "persistencia" en la configuración fue configurar la computadora para que cada vez que se detecte que la cámara web se conectó, se ejecute el comando "v4l2ctrl" para que "cargue" un archivo que coloqué en un lugar fijo.

Esto se logra con "udev". Específicamente, con una regla que diga exactamente lo que expliqué: en lo que se detecte la conexión de la cámara web, ejecutar el comando.

Las reglas udev se escriben en un archivo que termine en .rules, que debe estar ubicado en la carpeta /etc/udev/rules.d . Un artículo que utilicé para guiarme en la escritura de las reglas udev fue Writing udev rules por Daniel Drake (dsd). En mi caso, escribí un archivo llamado local.rules con el siguiente contenido:

SYMLINK=="/dev/v4l/by-id/usb-SQ_Tech_CO.__LTD._USB_2.0_PC_camera-video-index0", RUN+="/usr/bin/v4l2ctrl -l /opt/webcam_creative_values"
 
Y luego de reiniciar la máquina[1], cada vez que se detecte la cámara web, automáticamente se cargará la configuración contenida en el archivo /opt/webcam_creative_values . 
[1] Intenté no reiniciarla, reiniciando sólo el servicio udev, pero no me funcionó.

Este archivo webcam_creative_values, se crea previamente con el comando v4l2ctrl y la opción de "guardar", luego de estar conforme con los valores establecidos.

El contenido de mi archivo local.rules representa una regla udev, que está conformada en este caso por una clave de coincidencia ("match key" en inglés) y una asignación.

La clave de coincidencia es:

SYMLINK=="/dev/v4l/by-id/usb-SQ_Tech_CO.__LTD._USB_2.0_PC_camera-video-index0"

Que significa: si el dispositivo tiene el enlace simbólico "/dev/v4l/by-id/usb-Bison_HD_Webcam-video-index0" entonces se ejecutará la siguiente asignación.

La asignación es:

RUN+="/usr/bin/v4l2ctrl -l /opt/webcam_creative_values"

Que significa: a la lista de comandos a ejecutar, añade el siguiente comando: "/usr/bin/v4l2ctrl -l /opt/webcam_creative_values", que es el que carga los valores deseados en la cámara.

¿Cómo supe la ruta dentro de /dev/ de la cámara?

Un poco de cultura general de Linux es suficiente para saber que todos los dispositivos de la computadora están en algún lugar dentro del directorio /dev. Ahí se encuentran subdirectorios para los discos, el ratón, teclado, etc. Incluso, tiene un directorio dedicado a los dispositivos de entrada de video, como la cámara web. Este directorio es /dev/video0. Si hubieran más dispositivos de entrada de video, el cero (0) se cambiaría por un uno (1) para el siguiente dispositivo, un dos (2) para el que le sigue, y así. Ejemplo: /dev/video1, /dev/video2.

udev provee nombres persistentes para los dispositivos, para que no haya duda a la hora de escribir las reglas. Por ejemplo, /dev/video0 es la primera cámara web que conectamos y /dev/video1 es la segunda. Pero si se quiere escribir una regla para una cámara específica (tal marca, tal modelo, etc.), como en mi caso, se puede sacar provecho a los nombres persistentes que genera udev. Ellos están en algún subdirectorio llamado by-id. Para conseguir el nombre persistente de la cámara /dev/video0, por ejemplo, se ejecuta el siguiente comando:

$ udevadm info -q symlink -n /dev/video0

Este comando muestra todos los otros nombres que tiene asignada la cámara en este instante:

v4l/by-id/usb-SQ_Tech_CO.__LTD._USB_2.0_PC_camera-video-index0
v4l/by-path/pci-0000:00:1d.7-usb-0:8:1.0-video-index0

Se utilizaría entonces el que tiene by-id en la regla udev.

Pendiente

Esta solución no está del todo completa. Cada vez que modifique los parámetros de la cámara debo guardarlos con el programa v4l2ctrl en el el directorio /opt/webcam_creative_values, porque así lo establece la regla que yo mismo escribí.

Me gustaría que fuera automático. Como pasa con los otros parámetros de tipo "software": que yo no hago nada, esos valores se mantienen.

Creo que pudiera investigar dos cosas:
  1. ¿Dónde se almacenan los valores de esos parámetros? para ver como forzar la persistencia en ese lugar de los parámetros ganancia y exposición.
  2. ¿Cómo disparar un comando sólo cuando se desconecta un dispositivo?. Tal vez sea posible guardar los valores que están establecidos para la cámara después que se desconecte, sobrescribiendo el archivo en /opt, y logrando que la próxima vez que se conecte la cámara se restauren esos valores.

sábado, febrero 01, 2014

Extraña y grata sorpresa con la VIT P3400-2

El pasado miércoles pude comprar una portátil VIT P3400-2. Sus especificaciones técnicas son muy buenas: procesador Intel Core i7, 8GB de memoria RAM, 1TB de disco duro.

Usándola me percato de un par de "dispositivos" adicionales, como si tuviera dos "pen drives" conectados. Uno se llama Datos y otro SSD (con el último me emocioné del solo leerlo).

Para ver qué pasaba, analizo las particiones con "gparted". Primero, entiendo que Datos es simplemente una partición con sistema de archivos NTFS, tal vez para preparar la máquina a una eventual instalación de Windows y así no pierda el usuario todo su trabajo. Pero ¿dónde está la partición SSD?.

¡Sorpresa!¡No hay! es un dispositivo de almacenamiento a parte, es decir ¡Otro "disco" duro! (disco entrecomillas). Analizo mejor la situación con la "Utilidad de disco" y confirmo que hay dos dispositivos de almacenamiento. Y, como puede apreciarse en la imagen a continuación, el disco adicional es un disco de estado sólido de 32Gb; grata sorpresa:


Un "disco de estado sólido" es en realidad un dispositivo de almacenamiento muy parecido a los "pen drive" debido a que no tiene ningún "disco" ni piezas mecánicas que hagan girar a los mismos ni controlar los brazos lectores. La diferencia con los "pen drive" es que tienen un tiempo de vida mayor y por lo general mayor capacidad de almacenamiento.

La primera vez que supe de esta tecnología fue cuando se anunció el Mac Book Air. Una de las varias maneras en las que los diseñadores de Mac lograron reducir el peso de esa portátil fue sustituyendo los discos tradicionales con discos de estado sólido. Con este cambio, no sólo ganaron "ligereza", si no que la velocidad de arranque y de uso en general se incrementó muchísimo.

Hoy día es muy común que las portátiles utilicen discos de estado sólido por las ventajas descritas, a pesar de sacrificar capacidad de almacenamiento. Hay quienes dicen que 32GB es suficiente, que el resto puede almacenarse en un disco duro externo. También existen versiones híbridas que combinan discos duros de alta capacidad de almacenamiento tradicionales con discos de estado sólido, delegando en el disco de estado sólido el rol de almacenamiento caché.

Con la misma "utilidad de disco" le hice unas pruebas de velocidad sencillas a los dos discos, sólo por despejar las dudas:

Prueba de velocidad sobre el diso de estado sólido Velocidad promedio de 213,8 MB/s
Prueba sobre el disco de estado sólido Velocidad promedio de 213,8 MB/s

Prueba de lectura sobre el disco normal de 1TB. Velocidad promedio de 91,3 MB/s
Prueba sobre el disco normal de 1TB. Velocidad promedio de 91,3 MB/s

Pues si, es otro dispositivo, y es tan rápido como me lo esperaba. Que interesante ver cómo se mantiene el rendimiento casi constante del disco de estado sólido mientras que el disco normal no puede mantener su rendimiento: debe ser por las propiedades físicas del mismo (discos, brazos mecánicos) y el algoritmo de la prueba.

Algo que me llama muchísimo la atención es ¿Por qué no está en las especificaciones técnicas de la VIT?. De haberlo sabido hubiera elegido más rápido ese modelo.

Ahora, me gustaría realmente sacarle provecho a este disco. Creo que debería instalar el Sistema Operativo ahí, o por el contrario, buscar qué recursos necesitan una alta tasa de velocidad de lectura ¿Qué recomendaciones pueden darme?.

martes, octubre 01, 2013

Tres PPA/Repositorios que he registrado en los últimos días

ubuntugis-unstable

Luego de tanto alboroto en la web por el anuncio de QGIS 2.0, decidí probar esta nueva versión de dicha aplicación.

Siempre había utilizado el PPA estable de ubuntugis. Este PPA es muy interesante ya que compila un conjunto de software muy rico dedicado específicamente a los Sistema de Información Geográfica (SIG), haciendo de Ubuntu una plataforma más que completa para el trabajo de las personas relacionadas con este campo (Geógrafos, geoestadístas, geo*, etc.). Esta compilación la mantiene el equipo ubuntugis en Launchpad.

Sin embargo, para la fecha, la versión estable del PPA en cuestión no incluye QGIS 2.0. Es por esta razón que registré la versión inestable del PPA de ubuntugis:

$ sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable
$ sudo apt-get update
$ sudo apt-get install qgis

octave-stable

En un taller de Matlab, que yo estaba realizando Octave, me di cuenta de algunas funcionalidades que no estaban en Octave. Pero Google me decía lo contrario: esas funciones sí están en Octave. El problema es que la versión de Octave que viene en los repositorios oficiales de Ubuntu no es la más actualizada. La solución: instalar el PPA de el equipo de Octave en Launchpad.

$ sudo add-apt-repository ppa:octave/stable
$ sudo apt-get update
$ sudo apt-get install octave

R

En el caso de R, no pude conseguir un PPA adecuado en Lauchpad. Siguiendo las instrucciones del proyecto R para instalar R en Ubuntu (el enlace apunta al espejo que está en Venezuela, en la Universidad de Carabobo), añadí el repositorio, registré las llaves de autenticación necesarias, e instalé R. De esta manera, obtuve una versión de R bien actualizada.

$ sudo add-apt-repository "deb http://camoruco.ing.uc.edu.ve/cran/bin/linux/ubuntu precise/"
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9
$ sudo apt-get update
$ sudo apt-get install r-base r-recommended littler ess

littler permite ejecutar scripts de R de forma más tradicional (a la Unix).
ess es un modo de Emacs para trabajar con R.

Reflexión

Analizando en retrospectiva las acciones descritas, me doy cuenta que lo primero que intento hacer cuando quiero tener una versión actualizada de un software en específico, es conseguir un PPA confiable.

Los criterios de confianza que aplico son: el PPA de un equipo de trabajo relacionado directamente con el empaquetado en los repositorios de Ubuntu; el PPA del equipo de desarrollo del software; el PPA de alguien reconocido.
Si estos criterios no se cumplen, entonces prefiero descargar el software de los recursos que disponga el mismo equipo de desarrollo de dicho software.

miércoles, julio 31, 2013

PyPy 3

Buenas noticias[1]. Han liberado PyPy3 2.1 beta 1. Es la primera versión de PyPy que es compatible con Python 3.
PyPy es un intérprete de Python que se basa en un compilador JIT (Just In Time [2]) que tiene un desempeño muy competitivo, tanto, que está "postulado" para sustituir el intérprete CPython[3].
[3] CPython es el intérprete de Python que mantiene la Python Software Foundation, y el más utilizado. Es una implementación de Python escrita en lenguaje C (de ahí su nombre). Se considera la "implementación de referencia".

domingo, septiembre 02, 2012

Detalles sobre una instalación nueva de Ubuntu 12.04 en mi oficina

La gran pesadilla hasta ahora ha sido el proxy y el firewall de mi lugar de trabajo.
Desde las versiones 11.X de Ubuntu empecé a utilizar el entorno Unity de Ubuntu. Al principio no me gustó mucho pero empecé a entender las razones de su diseño: por ejemplo, el principio de que los píxeles valen [1]. Luego de darle una oportunidad y en la medida en que iba actualizando mi sistema hasta llegar al 12.04, creo que ya Unity tiene bastante madurez y puedo decir que me gusta el entorno. Ahora, en ese proceso he venido acarreando las aplicaciones que tenía instalada desde el 11.X y se que hubo muchos cambios en cuanto a las aplicaciones instaladas por omisión en un entorno Ubuntu. Así que por la curiosidad de entender qué es lo que la gente de Ubuntu define como su escritorio (si es que podemos seguir usando esa metáfora o ya es hora de pensar en una nueva) o mejor dicho, su sistema, quise hacer una instalación desde cero y darle una oportunidad a las aplicaciones que ellos sugieren y experimentar bien cómo se integran al resto del sistema (y cómo lo hacen, es algo que también me llama la atención); excepción: Emacs, ya instalado.
Sin embargo, hacer esto en una organización que tiene un firewall y un proxy clásicos, no es tan divertido. Así que quise dejar aquí algunas notas de las cosas que tuve que tomar en cuenta antes y después de la instalación desde cero en mi oficina.
[1]Tal vez hago referencia a otro libro acerca de diseño, pero solo con ir a la Guía del escritorio de Ubuntu se puede uno enterara de que el diseño del nuevo Ubuntu busca minimizar las distracciones, aumentar el espacio de trabajo y ayudar al usuario a realizar sus tareas.

Respaldo

Por supuesto, este es el primer paso. Respaldar los datos importantes: documentos, imágenes, música, etc. Basta con copiarlos en un medio de almacenamiento externo como un CD/DVD o un disco duro externo.
Sin embargo, con respecto a los correos electrónicos y los contactos tuve que hacer algunos pasos adicionales.
Primero, he estado usando Evolution hasta ahora. Por ahora bastaría con el respaldo clásico, y se supone que importar esos correos desde Thunderbird es directo porque teóricamente usan el mismo formato de correo: Mbox. Sin embargo, hay una consideración en mi caso: había usado Evolution desde hace tiempo que me enteré que tenía los correos en un formato de correo viejo: Maildir que es mejor exportarlos a Mbox antes de hacer el respaldo, para que no tenga que instalar Evolution al final para poder transformar los correos a Mbox (tal vez no fuera necesario, pero era un riesgo que no tenía que pasar). Para esto, usé un script que recomendaron en una respuesta en AskUbuntu . Al final, el respaldo es un archivo en formato Mbox que debe guardarse en el medio de respaldo elegido.
Con respecto a los contactos desde Evolution, simplemente clic derecho a la libreta que se quiera respaldar y se exporta (normalmente a formato Vcard)
Luego del respaldo, viene la instalación. No escribiré al respecto, solo que instalé de la forma más directa: "siguiente siguiente siguiente".

La Red (el caso del Proxy)

Si tienes una computadora portátil, sufrirás las consecuencias de hacer todo lo que aquí se indica, porque cada vez que se cambie de lugar de acceso a Internet, habrá que volver a configurar el proxy.
Después de instalar el sistema lo primero que se haría es actualizar el sistema, pero esto no es tan trivial en mi oficina. Primero se debe configurar la red.
Si fuera el caso de una computadora nueva en la organización, habría que decirle al departamento de IT cuál es la dirección MAC de la máquina. Pero ya que estoy usando la misma máquina de siempre, no hace falta.
Luego, conectarse no debería ser muy difícil en Ubuntu: se conecta el cable y listo, o si se quiere usar la red inalámbrica, basta con colocar la contraseña cuando se pida.
La parte fastidiosa del cuento es el proxy.
Le Proxy
El malo de la película. No tienen idea cuánto lo odio, cuántas horas me ha hecho perder... ¡TE ODIO PROXY!. (Proxy suena a nombre de mujer, tenía que ser, que mujer tan enrollada).
El problema es que aparentemente soy la primera persona en la organización que no usa la Internet solo con Firefox, sino que a veces necesito wget y/o curl, bajar cosas con Emacs (paquetes de Emacs), Gwibber para el Twitter, todo el tema de APT para mantener mi sistema actualizado (y como no existe un repositorio en la organización...) o a veces conexiones no web: IRC y FTP por ejemplo (esta última parte no entiendo qué tiene que ver con el proxy, pero es así, aparentemente; si alguien puede explicarme por qué puede un proxy como squid fastidiar al IRC, se lo agradezco).
Bueno, empezamos con lo básico. La configuración del proxy en Ubuntu se hace en la configuración de red: SUPER seguido de 'red' y ENTER, o en el menú de configuración que se encuentra en el menú de arriba a la derecha.
Ahí hay una configuración por cada interfaz de red que tenga la máquina y por último está la configuración del proxy. Se puede determinar que no hay proxy; o configurar un proxy manualmente, en cuyo caso habría que colocar el nombre o la IP del proxy y el puerto; o, como en mi caso, la configuración automática, en donde se coloca la url de un archivo de configuración automático.
En un mundo ideal, esto debería bastar: todas las aplicaciones que eventualmente hagan uso de la web deberían verificar esta configuración para saber cómo usar el proxy. Pero en este aspecto, Ubuntu no es para nada ideal. Aquí una opinión: ¿Cómo es que con la configuración de red de Gnome basta para que todas las otras aplicaciones se puedan conectar a la red pero no puedan saber cuál es el proxy. El problema es peor y más triste aún: hay aplicaciones gráficas (de Gnome) que no usan esta configuración del proxy, por ejemplo Gwibber y Empathy (de hecho, hasta ahora no he podido resolver esto, así que me conecto al IRC por el webirc de Freenode).
Para que aplicaciones como wget y curl funcionen con el proxy, deben estar definidas las variables de entorno http_proxy y https_proxy.
Las variables de entorno http_proxy y https_proxy deben tener la url de conexión al proxy de la organización. Para que queden permanentemente establecidas esas variables, se coloca lo siguiente en el archivo .bashrc (ajustar a cada caso):
http_proxy="http://proxy.leorg.org:1080/"
https_proxy="https://proxy.leorg.org:1080/"
export http_proxy https_proxy
Todavía falta algo para poder hacer un apt-get update. Resulta que al hacer sudo apt-get update las variables de entorno se pierden, así que para mantenerlas hay que invocar sudo con la opción -E. Pero si queremos usar las interfaces gráficas de APT, como el Gestor de actualización o el Centro de software de Ubuntu hay un problema: ellos no los invocamos normalmente desde la consola, así que no tenemos tiempo de pasarles las variables de entorno a través del sudo.
La solución, seguir las recomendaciones de este artículo, editar el archivo apt.conf:
Acquire::http::Proxy "http://proxy.leorg.org:1080";
Acquire::https::Proxy "http://proxy.leorg.org:1080";
Pero hay un detalle que todavía causa problemas con las interfaces gráficas de APT y el proxy. A veces, un paquete invoca algún script durante el proceso de instalación, y este puede a su vez intentar conectarse a la web con programas como wget. Bueno, como es gráfico y obtuvo las credenciales por otro medio diferente de sudo (por lo cual no le pudimos decir con la opción -E que conserve las variables de entorno) entonces, ese wget no va a saber cómo conectarse al proxy. La solución, es fijar las variables de entorno del proxy al sudo. Para ello se usa el programa visudo y se agrega lo siguiente:
Defaults env_keep = "http_proxy https_proxy ftp_proxy"
Con todo esto, ya tenemos bien dominado a todo lo que es APT, y varias aplicaciones que no toman la configuración de Gnome, pero todavía me quedan pendientes:
  1. Emacs y ELPA
  2. Empathy
  3. Gwibber
IRC no web es lo que más extraño.

Restauración

Para la restauración del respaldo, solo con respecto al correo y los contactos fue algo diferente a trivial (de resto, una simple copia).
Instalé el complemento de Thunderbird llamado ImportExportTools, luego hay que darle clic derecho a la bandeja de entrada, menú Importar/Exportar, opción Importar mbox y elegir Importar uno o más archivos con sus subcarpetas. En ese momento, una ventana de diálogo te permite elegir el archivo mbox a importar, que será el que se respaldó antes de instalar Ubuntu.
Los contactos se importan desde la vista de Libreta de direcciones, en el menú Herramientas, opción Importar.

Algunos paquetes que instalé luego

Emacs
La versión de Emacs que proveen los repositorios oficiales de Ubuntu es la 23. Pues la versión 24 trae una gran cantidad de mejoras que no quería perderme, entre los que más me interesan está el nuevo sistema de gestión de paquetes ya oficialmente soportado por Emacs.
Para poder instalarlo a la Ubuntu registré un PPA (Personal Package Archive) que mantiene unos paquetes de Emacs bien actualizados. Lo conseguí gracias a este artículo.
Los pasos que seguí:
$ sudo apt-get update
$ sudo add-apt-repository ppa:cassou/emacs
$ sudo apt-get update
$ sudo apt-get install emacs24 emacs24-el
Con esto ya tenemos el Emacs24 instalado. Irónicamente, el sistema de gestión de paquetes, la principal razón de instalar esta versión de Emacs, no funciona al 100% porque el proxy no le permite conectarse a los repositorios. Se puede configurar el proxy en Emacs, pero no he podido hacer que funcione todavía.
Otra cosa que tengo pendiente es instalar el soporte completo al idioma español en Emacs y el diccionario de Aspell.
Retoque a LibreOffice
De un excelente artículo acerca de cosas que retocar en Ubuntu después de instalarlo, rescaté, entre otras cosas, la habilitación del menú global para LibreOffice.
Lamentablemente en esta nueva versión de Ubuntu LibreOffice no hace uso del menú global, que es la nueva forma de interactuar con las aplicaciones en Ubuntu, exactamente igual que en MacOS. Se trata de que el menú de todas las aplicaciones se funde con la barra superior del sistema que ya contiene otras cosas como el espacio para las notificaciones, ahorrando bastantes píxeles verticales (que aparentemente son más importantes que los horizontales, ya que el lanzador no desaparece de manera automática como hacía antes).
Para hacer que LibreOffice respete el menú global, basta con instalar el paquete lo-menubar:
$ sudo apt-get install lo-menubar
Restricted Extras
Sin entrar en polémicas, por los mp3 y otros formatos de video:
sudo apt-get install ubuntu-restricted-extras
Cabe acotar que este paquete invoca a un script que intenta bajar archivos de la Web. Si el proxy no está configurado en sudoers (y en todos lados por si a caso) entonces fallará.
Y para escribir en el blog
  • python-docutils
  • rst2pdf
  • mercurial
Solo faltaría configurar mercurial con por lo menos los datos personales del usuario:
$ cat > ~/.hgrc
[ui]
username = Jesús Gómez <jgomo3@gmail.com>
Ctrl-D

Siempre me toca hacer lo siguiente en el Terminal de Gnome

Estoy muy acostumbrado a las combinaciones de teclas de Emacs en el terminal, pero la tecla ALT y F10 disparan otros eventos propios del entorno gráfico (seleccionan el menú de la aplicación, en este caso el terminal de Gnome).
Para evitar que esto pase y funcionen como en Emacs, se modifican las configuraciones pertinentes en la opción Combinaciones de teclas... en el menú Editar. Ahí, se desactivan las teclas de acceso al menú y F10.

Decepciones

  • ¡¡¡PROXY!!! No entiendo cómo no hay una solución única a este rollo.
  • Tenía la esperanza de que una actualización limpia desapareciera ese bug de Firefox tan maldito: arrastra una imagen y TODO el sistema se congela por un minuto aproximadamente.

jueves, febrero 09, 2012

Mejorar como programadores - El Comienzo

La Idea

Inspirados en el artículo Kicking ass together: How to improve coding skills as a group, Luis y yo escribimos este artículo como un preámbulo a una etapa de trabajo en la que pretendemos implementar algunas de las ideas ahí planteadas.
El martes 10 de enero concertamos una reunión personal en el café de la nueva plaza de Los Palos Grandes. Muy buen lugar para el esparcimiento y reunirse. Tres copias impresas del artículo que se procesaron exageradamente con Readability (digo exageradamente porque pare ser sincero, no era necesario) sirvieron de guía durante la reunión, en la cuál principalmente hablamos de dicho artículo y de cómo llevar a cabo esas ideas aplicándolas en nuestro contexto.
El artículo es de gran interés para nosotros porque llevamos tiempo realizando reuniones que seguían más o menos esas ideas; pero al verlas condensadas en un solo texto, integradas, y ejecutadas inteligentemente, reconocimos su gran valor.
Otro artículo que nos motivó bastante fue 12 resolutions for programmers que apunta básicamente a las mismas motivaciones del primer artículo: Ser mejor persona para ser mejor programador (sustituye programador con lo que quieras y sirve igual). Queremos mejorar nuestras habilidades, de eso no hay duda, y sabemos que en Buen equipo lo haremos de mejor manera: más rápido, más amplio, más seguro (más probable).
La gente de Jelly hizo algo similar. El enfoque que le dieron es el de "vamos a llevar el ambiente de oficina a otra parte".
Al finalizar el año, haremos un análisis de lo logrado con este meta-proyecto.

El Grupo

Todas las ideas planteadas en los artículos mencionados (a excepción del de las doce resoluciones), o en las reuniones que hemos tenido, giran alrededor del concepto de un grupo. Sería entonces el medio más importante para lograr el objetivo de mejorar personalmente. Así que uno de los primeros objetivos a corto plazo sería la consolidación del mismo.
Siguiendo las recomendaciones de los textos, y la experiencia propia, planteamos al grupo como un ente orgánico, en el sentido de que su evolución sea lo más natural posible, es decir, no forzaremos su crecimiento, las iniciativas deben venir de las bases y los objetivos y actividades serían planteadas en función de la madurez del grupo, es decir, ya tendremos tiempo para un BigDeepShitCON, pero por ahora, proyectos concretos y tangibles en corto plazo son nuestros objetivos.
Como ejemplo de estos proyectos:
Hack 7 Languagess in 7 weeks
El libro Seven Languagess in Seven Weeks pretende explicarle a entendidos en la programación, siete lenguajes representativos de los más diferentes paradigmas de programación. Entonces, como actividad de grupo nos hemos planteado leer este libro y comentarlo entre nosotros, hacer los ejercicios y comparar las soluciones y/o simplemente apoyarnos mutuamente en el seguimiento del mismo.
Track le blogs
Una de las resoluciones asumidas fue la de mantener un blog. Entonces, en el grupo nos apoyaremos leyendo los blogs de los compañeros y generando feedback.
Maratonear
Para mantener a punta nuestras habilidades esenciales de la programación, haremos ejercicios concertados de programación clásicos de los maratones. Como ejemplo, los problemas de spoj, luego de solucionarlos, compararemos las soluciones, y también discutiremos ideas durante el desarrollo de las soluciones.
Desarrollo de aplicaciones
Siempre surgen ideas de aplicaciones útiles durante las reuniones. Podemos ejercitar el trabajo en un buen equipo de desarrollo de software implementando estas ideas en el marco del meta-proyecto.
Para materializar los resultados esperados, el trabajo se realizaría en sesiones presenciales y no presenciales.

Sesiones de trabajo presenciales

Con el objetivo claro de mejorar y tomando el artículo como guía, nos propusimos realizar un conjunto de sesiones periódicas de trabajo. Éstas consistirán en una hora de trabajo y una hora de socialización. Entendemos que, para mejorar, ambas actividades son igual de importantes.
Las sesiones de trabajo deben incorporar actividades que mejoren las habilidades de cada uno de los participantes. Algunas de las actividades que identificamos que cumplen con este requisito son solucionar problemas de programación, hacer code reviews, etc.
En estas sesiones de trabajo, también se podrán realizar charlas de interés para los participantes del grupo.
Las sesiones de trabajo y socialización están abiertas a cualquiera que quiera asistir a ellas, y la única condición es participar y aportar desde el primer momento. Cualquier comentario dentro de contexto se considera participación.

Sesiones de trabajo en linea

Siguiendo el ejemplo de numerosos proyectos de Software Libre, resulta sencillo ejecutar de manera remota casi la totalidad de las actividades que nos hemos planteado. Nos referimos a las herramientas clásicas de las que se valen estos proyectos para coordinar el trabajo de tantos participantes localizados en lugares remotos del globo, a saber: Sistemas de Control de Versiones Descentralizados, documentación en línea, IRC, wikis, blogs, etc.

El Comienzo

Puede interpretarse como una nueva disciplina. Tal vez como un simple programa de ejercicios rutinarios. Tal vez un hobby. En cualquier caso, se trata de algo positivo.
Pero lo que sí es cierto, es que lo que hemos escrito, es los planes de su primera etapa (sea lo que sea).

miércoles, noviembre 23, 2011

Ciclo redactar publicar con Blogger

Tengo la intención de escribir varios artículos en este blog:
  • Despliegue en Django
  • Mi presentación de Git
  • La conferencia Mejorando la web
  • Cita al ensayo sobre SOPA creado por @danielmaxx
  • Algunas cosas viejas que escribí por ahí
Pero habiendo colaborado en algunas revisiones de El blog en español de Python Insider quise poner en práctica el mismo workflow que ellos aplican. Y es lo que estoy haciendo justamente ahora mientras escribo este artículo acerca del mismo workflow (y lo que haré de ahora en adelante).

Le workflow

El mencionado workflow está explicado en el wiki del proyecto de los blogs de Python. Pero básicamente se basa en utilizar un repositorio bajo control de versiones donde un convenio en el uso de los directorios permite distribuir el trabajo.
La parte interesante del workflow es que el trabajo de redacción no se hace en la interfaz que para ello disponga el sitio que almacena y publica los artículos (en nuestro caso, la interfaz web de Blogger), sino que se redacta en un archivo dedicado al artículo, y ese archivo se mantiene en control de versiones. Luego, cuando se esté conforme con el resultado, se publica utilizando un script que sube el archivo como si fuera el artículo (también pudiera usarse el copiar y pegar con la interfaz web).
En particular, el proyecto de los blogs de Python utiliza mercurial como sistema de control de versiones, bitbucket es donde almacenan su repositorio, reStructuredText es el lenguaje de marcas que utilizan para estructurar y formatear los artículos y un script en Python [1] muy específico para subir el archivo al blog.
Una de las más grandes ventajas de trabajar de esta manera es el soporte en la coordinación del trabajo de varias personas sobre el mismo producto que se obtiene al usar el sistema de control de versiones y un repositorio compartido.
Pero cuando se usa para un blog como el mío que solo tiene un autor, todavía hay ventajas.
Primero, el control de versiones. Pero esta vez, en vez de referirme al poder de coordinación, me refiero a la ventaja de contar con versiones que reflejen la evolución de lo que escribo y poder echar para atrás los cambios que quiera.
Segundo, escribir en tu lenguaje de marcas preferido ... punto.
Tercero, escribir en tu editor de texto preferido ... punto.

Ejemplo

Como ejemplo de cómo trabajar con este workflow voy a explicar cómo he escrito esta entrada y cómo lo publiqué.
Le script
El script en Python se llama rst2blogger.py. Se usa la siguiente manera:
$ rst2blogger.py <blog> <.rst>
Lo que hace es convertir el archivo .rst en un contenido en formato html y trata de subir ese contenido en el blog blog. Para ello te pide que te autentifiques con los servicios de Google.
Como este es un script que rápidamente se hizo para este workflow de los blogs de Python, entonces hay que modificarlo un poco para que sirva con el de uno.
Lo primero que hace el script después de todos los imports es definir un diccionario llamado BLOG_IDS, asocia una etiqueta al identificador único del blog. Entonces, simplemente se añade el blog de uno en ese diccionario. Por ejemplo, el identificador único de mi blog es 15836385 [2], entonces asocie el identificador jgomo3 con él. Queda algo así:
# local
import rst2post

BLOG_IDS = {
    'jgomo3':'15836385',                # jgomo3's blog
    'clienttest':'4574580403850978202',
Hay que aclarar dos cosas acerca del script:
  • Él pica el contenido en dos partes: el título, y el resto. Entonces, el título con el que sube el artículo va a ser el que le coloques como título principal en el .rst.
  • La primera vez sube el artículo como un borrador nuevo. Las siguietes veces que publique el mismo blog, simplemente actualiza el blog. Para publicar, se hace desde la interfaz administrativa de Blogger.
Como alternativa a este script, pudiera lograrse algo parecido con una combinación entre rst2html y googlecl.
Le repo
Creé un repositorio en bitbucket para mantener el blog (de ahora en adelante).
Luego, lo cloné en mi máquina para trabajar:
$ hg clone https://bitbucket.org/jgomo3/jgomo3-blog
Siguiendo el convenio de los blog de Python, definí dos directorios:
  • InProgress: que contiene los artículos "en progreso", es decir, los borradores.
  • Published: que contiene los artículo ya publicados en el blog.
$ install -d InProgress Published
Entonces, el trabajo es evidente. Cuando se quiere empezar un nuevo artículo, simplemente se crea un archivo en la carpeta InProgress. Luego, un hg add para hacerle seguimiento con mercurial. hg commit por cada cambio relevante que queremos recordar con mercurial y cuando queramos salvaguardar el trabajo en bitbucket, un hg push (así además puedes mostrar el trabajo a terceros para que le echen un ojo y si quieren pueden colaborar).
$ cd InProgress
$ hg add ciclo-redactar-publicar-blogger.rst

... Ciclo largo de trabajo
.
.    ... Ciclo corto de trabajo
.    .   $ [tu editor favorito o emacs] ciclo-redactar-publicar-blogger.rst
.    .   $ rst2html ciclo-redactar-publicar-blogger.rst > test.html
.    .   # Ver el archivo test.html en un navegador
.    ...
.
... $ hg commit

$ hg push
Le blog
Una vez esté terminado el artículo y se quiera publicar en el blog, se ejecuta el script:
$ rst2blogger.py jgomo3 ciclo-redactar-publicar-blogger.rst
Esto creará un borrador en Blogger. Entonces se navega a Blogger, se aprecia cómo se ve el borrador, se le asigna la fecha de publicación al artículo y se publica.
Por último, se mueve el artículo de la carpeta InProgress a la carpeta Published y se actualiza el repositorio en bitbucket:
$ hg mv ciclo-redactar-publicar-blogger.rst ../Published
$ hg commit
$ hg push
Le FIN
Como ya comenté, de ahora en adelante usaré esta técnica para escribir en el blog.
Por último, por si no lo notaron, mi editor favorito es Emacs, y dejo a su disposición un par de artículos que explican esta misma idea pero desde el punto de vista de un par de emacseros y usuarios del org-mode.
[1]Deben estar todos los archivos .py en el mismo lugar.
[2]Para saber cuál es el identificador único de tu blog en Blogger simplemente observa la barra de direcciones de tu navegador mientras lo editas.