Archive for March, 2009

Snippets en Vim con snipMate

Basado en el editor TextMate (mac), snipMate.vim es un plugin que permite insertar pedazos de código de uso frecuente simplemente tipeando parte del mismo y apretando<tab>.

Por ejemplo, supongamos que estamos editando un programa en C y queremos agregar un ciclo for, simplemente escribimosfor<tab>y esto se expandirá en un típico bucle de C

for (i = 0; i < count; i++)
{
    /* code */
}

Inmediatamente después el cursor quedará resaltando la palabra “count” para que podamos reemplazarla por nuestra condición de fin. Un par de tabs más nos llevarán al cuerpo del ciclo donde podremos seguir utlizando snippets comopr<tab>, lo que expandirá en la función printf

for (i = 0; i < 10; i++)
{
    printf("%s\n");
}

snipMate tiene una sintáxis muy sencilla (según dicen, muy similar a la usada por TextMate) lo que permite crear nuestros propios snippets, o mejorar los existentes. La versión actual (0.77) trae una colección de snippets para los siguientes lenguajes: C, Obj-C, C++, Sh, TeX, Java, Ruby, Perl, Python, PHP, JavaScript, y HTML.

El proyecto parace estar bastante activo y la última versión es del 30/03/2009.

Tags:

Accediendo a MySQL con Python y MySQLdb

MySQLdb es un módulo que implementa la API estándar (PEP249) para manejo de bases de datos, en este caso MySQL. MySQLdb es en realidad un wrapper del módulo _mysql que provee Python, el cual implementa la mayoría de las funciones definidas en la API C de MySQL. La idea de definir una API estándar es que uno debería poder cambiar a otra base de datos sin modificar demasiado el código.

This API has been defined to encourage similarity between the Python modules that are used to access databases.

Instalación MySQLdb

El paquete que nos provee el módulo se llama python-mysqldb. Podemos comprobar que lo tenemos instalado mediante

dpkg --get-selections | grep python-mysqldb

Si no existe lo instalamos

sudo apt-get install python-mysqldb

Para comprobar que efectivamente tenemos el módulo disponible y funcionando llamamos al intérprete de Python y escribimos

>>> import MySQLdb

Un silencioso retorno de carro indica que podemos el módulo ha sido cargado. Salimos del intérprete conC-d.

Creación de una DB de pruebas

Para nuestro ejemplo crearemos una base de datos con una única tabla. Entramos a la consola de MySQL y escribimos

mysql> CREATE database test;
Query OK, 1 row affected (0.01 sec)

mysql> USE test;
Database changed
mysql> CREATE TABLE users (
    -> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> name VARCHAR(100),
    -> lastname VARCHAR(100)
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO users (name, lastname) VALUES
    -> ('Juan', 'Perez'),
    -> ('Ana Maria', 'Lopez'),
    -> ('Carlos L.', 'Gutierrez');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

Nuestra tabla users quedó entonces

mysql> SELECT * FROM users;
+----+-----------+-----------+
| id | name      | lastname  |
+----+-----------+-----------+
|  1 | Juan      | Perez     |
|  2 | Ana Maria | Lopez     |
|  3 | Carlos L. | Gutierrez |
+----+-----------+-----------+
3 rows in set (0.00 sec)

Creación del script mysqldb.py

Creamos el siguiente script que se conectará a la base de datos test y traerá todos los datos de los usuarios cargados en la tabla users. En el script es necesario reemplazar <user> y <pass> por los datos requeridos para acceder a tu DB.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/python
import MySQLdb

# Conexion a la base de datos
conn = MySQLdb.connect (host="localhost",
    user="<user>", passwd="<pass>", db="test")

# Creacion cursor
cursor = conn.cursor()

# Ejecucion query
cursor.execute("SELECT * FROM users")

# Manejo de datos devueltos por la consulta
while True:
    row = cursor.fetchone()
    if row is None:
        break
    else:
        print "id: %s\tname: %s %s" %
            (row[0], row[1], row[2])

# Finalizado cursor y objeto conexion
cursor.close()
conn.close()

La salida debería ser

id: 1   name: Juan Perez
id: 2   name: Ana Maria Lopez
id: 3   name: Carlos L. Gutierrez

Links recomendados para ampliar conocimientos

Tags: , ,

GNU gettext con php5

gnu-head-sm

GNU gettext es la biblioteca GNU de internacionalización (i18n) y es usada para escribir programas con interfaz en múltiples idiomas.

wikipedia

La internacionalización es el proceso de diseñar software de manera tal que pueda adaptarse a diferentes idiomas y regiones sin necesidad de cambios de ingeniería ni de código. La localización es el proceso de adaptar el software para una región específica mediante la adición de componentes específicos de un locale y la traducción de los textos, por lo que también se le puede denominar regionalización.

Es una práctica común en el idioma inglés (sobre todo en el ámbito de la computación), abreviar internationalization como “i18n”. Ello se debe a que entre la primera i y la última n de dicha palabra hay 18 letras. Lo mismo sucede con localization, que se abrevia “L10n”.

gettext en PHP

Existen dos formas de usar gettext en PHP: mediante la extensión gettext nativa de PHP o utilizando la librería PHP-gettext, escrita en PHP, que no necesita ninguna extensión.

La forma de usar gettext es

1
2
3
4
# @file: index.php
<?php
print _("hello world");
?>

La función_(), alias degettext(), devolverá la cadena “hello world” en el lenguaje correspondiente, de acuerdo al locale que hayamos seleccionado.

Si ejecutamos el script obtendremos “hello world” como salida, puesto que no hemos indicado ningún locale, ni creado ningún catálogo de traducción. Necesitamos crear el archivocomments.pocon la traducción de la cadena “hello world”. Esto puede hacerse mediante el comandoxgettext, o mediante un editor gráfico como poEdit.

apt-get install poedit

Creación del catálogo con poEdit

Ante todo debemos saber que la estructura de directorios para guardar los distintos catálogos tiene forma determinada. Por cada traducción se utiliza un directorio. Este generalmente se nombra usando dos letras minúsculas para el idioma, un guión bajo y dos mayúsculas para el país (es_AR, para español de Argentina). Dentro de este directorio debe existir otro con el nombre LC_MESSAGES, el cual será finalmente el directorio que contendrá el catálogo.

La estructura de nuestro ejemplo será

.
|-- locale
|   `-- es_AR
|       `-- LC_MESSAGES
|           |-- messages.mo
|           `-- messages.po
`-- index.php

El archivomessages.moes la versión compilada demessages.poy el que usará PHP para obtener la traducción.

Iniciemos poEdit. La primera vez nos preguntará por nuestro nombre y correo electrónico. Estos datos servirán para saber quién fue el último traductor que modificó el catálogo. Una vez en la ventana principal vamos a File -> New catalog. Seleccionamos el idioma (Español en este caso), el país y el código de caracteres tanto para el catálogo como para la fuente de datos desde la que obtendremos el listado de cadenas que requieren traducción. En la solapa Paths debemos colocar en ‘Base path’ la ruta completa al directorio base de archivos php (conteniendo las cadenas mencionadas anteriormente) y, debajo, en el cuadro ‘Paths’ agregar una entrada con ‘.’ indicando que se debe utilizar el directorio ingresado anteriormente. Al hacer click en OK aparecerá un cuadro de diálogo para guardar el nuevo catálogo. Navegamos hasta el directorio LC_MESSAGES y guardamos el archivo como messages.po. poEdit escaneará el directorio ingresado en Paths y extraerá todos las cadenas gettext. Ahora queda simplemente realizar la traducción y guardar el archivo. Al guardarlo, poEdit lo compilará y generará el .mo que finalmente usará PHP.

Ahora, modificaremos index.php para setear el locale

1
2
3
4
5
6
7
8
9
10
11
12
13
# @file: index.php
<?php
$language = 'es_AR.UTF-8';
putenv("LANG=$language");
setlocale(LC_ALL, "");

$domain = "messages";
bindtextdomain($domain, "./locale");
bind_textdomain_codeset($domain, 'UTF-8');
textdomain($domain);

print _("hello world");
?>

Aun nos queda un paso y es comprobar que tengamos dicho locale habilitado en nuestro sistema. Esto lo hacemos mirando la salida de

locale -a

Si no tenemos habilitado el charset es_AR.UTF8, ejecutamos

locale-gen es_AR.UTF-8

En este punto la salida del script debería ser la traducción que hicimos al español.

Tip

Para casos en que la cadena a traducir contenga variables, podemos utilizar esta función:

1
2
3
4
5
6
7
8
9
10
function __($string)
{
    $arg = array();
    for($i = 1 ; $i < func_num_args(); $i++)
        $arg[] = func_get_arg($i);
    return vsprintf(gettext($string), $arg);
}

$total = 400;
print __("results %d - %d of about %d", 1, 20, $total);

La traducción podría quedar

resultados %d - %d de aproximadamente %d

Tags: , , ,