sábado, 21 de enero de 2012

Como traducir tus posts
How to translate your posts


he estado buscando la manera de traducir los post de blogspot, donde tengo alojado este blog,  pero no he encontrado nada. Así que me he puesto manos a la obra y he escrito un poco de javascript para añadir esta funcionalidad a mi blog. La idea es muy sencilla, el post contiene ambos textos, en inglés y en español, y mediante jQuery muestro uno u otro. También leo el parametro lang de la url para determinar en que idioma se debe mostrar el post para poder crear links en el idioma deseado.





Lo peor de todo es que ahora voy a tener que traducir los posts :(


I've been looking for a way to translate a blogspot's post, where my blog is hosted, but I haven't found anything. So I have started to work and I've written some javascript to add this feature to my blog. The idea is pretty simple, the post contains both texts, English and Spanish, and through jQuery show one of them. I read the parameter 'lang' from the url to determine which language must be display in order to create english or spanish links.



bad idea, now I have to translate the posts: (



viernes, 20 de enero de 2012

[Erlang] - Añadir un timer a un gen_server

En un proyecto que estoy desarrollando con Erlang necesito realizar unas comprobaciones periódicamente. El proyecto está basado en Erlang/OTP y para realizar dichas comprobaciones he añadido un gen server que, entre otras cosas, ejecuta un 'timer' periódicamente. En este post voy detallar el proceso que he seguido para añadir un 'timer' periódico a un gen server.

El proceso es muy simple, se envía un mensaje periodicamente al gen server con un mensaje concreto, y en la recepción de dicho mensaje realizamos la tareas necesarias, en este ejemplo mostramos un texto por pantalla.

Para realizar las llamadas periódicas al timer vamos a usar la función timer:send_interval/2.
send_interval(Time, Message) -> {ok, TRef} | {error, Reason}

Esta función se envía a sí misma el mensaje 'Message' repetidamente con un intervalo indicado en milisegundos (Time). Es decir, cada 'Time' milisegundos ejecuta 'Pid ! Message', donde el 'Pid' es el del proceso que lo ejecuta (Pid = self()).

Para leer el mensaje recibido en el gen_server utilizo el módulo handle_info/2.

A continuación se puede ver el código completo del gen server con un 'timer' periódico cada segundo.

sábado, 14 de enero de 2012

[Git] - Moviendo trabajo pendiente

En mis desarrollos, tanto personales como los profesionales, uso git. Tengo varias máquinas y a veces necesito mover trabajo inacabado de una a otra. No se debería hacer un commit con código que no funciona o sin terminar, o por lo menos este código no debería quedar almacenado en el arbol una vez terminado el trabajo. A continuación voy a poner la secuencia de comandos que sigo para subir al repo código sin terminar de manera temporal y como lo integro en la rama final una vez terminado.

Partimos de la máquina #1 con modificaciones de código pero incompletas, hacemos lo siguiente:

git stash
git checkout -b working-branch
git stash pop
git commit  -m 'working'
git push oringin working-branch


Maquina #2
Actualizamos  el código código con git pull
nos ubicamos en la rama que deseemos seguir con el trabajo que estabamos realizando y compiamos el commit que hemos llamado 'working'
git cherry-pick  <commit-ish>
seguimos trabajando hasta tener el código terminado y hacemos un nuevo commit con la opción --amend
git commit --amend -m 'mensaje definitivo'



martes, 20 de diciembre de 2011

[erlang] - Comparaciones en Erlang

Para realizar comparaciones en Erlang hay diferentes operadores. La principal diferencia es si se tiene en cuenta el tipo en dicha comparación.
Los operadores que no contemplan el tipo son:
== -> Comprueba si son iguales los valores que hay a cada lado del operador.
/=  -> Comprueba si son distintos los valores que hay a cada lado del operador.

Los que si contemplan el tipo son:

=:=  -> Comprueba si son iguales los valores que hay a cada lado del operador.
=/= -> Comprueba si son distintos los valores que hay a cada lado del operador.


Veamos un ejemplo, Vamos a comparar 1 (tipo entero) con 1.0 (tipo float).

1> 1 == 1.0.
true
2> 1 =:= 1.0.
false
3> 1 /= 1.0.
false
4> 1 =/= 1.0.
true

martes, 28 de junio de 2011

[Django, GAE] - Pruebas django y google app engine

EDITADO:
Obsoleto. Para crear aplicaciones django sobre GAE en la actualidad es mejor usar django-nonrel


¿Qué es Google App Engine (GAE)?

GAE te permite ejecutar aplicaciones Web en la infraestructura de google. Existe una versión Java y otra Python.

http://code.google.com/intl/es-ES/appengine/docs/

GAE admite cualquier framework creado en su totalidad con Python que utilice el estándar CGI (y cualquier framework compatible con WSGI que utilice un adaptador de CGI), incluidos Django, CherryPy, Pylons y web.py. Como ya tengo experiencia con Django me he decantado por este framework. El principal problema a la hora de usar Django con GAE, es la diferencia que hay entre las bases de datos y por lo tanto en los modelos. GAE sólo permite el uso de su base de datos por lo que es necesario adecuar los modelos de Django a este almacén de datos.

Para poder usar Django con GAE, se ha creado un helper que se puede encontrar en http://code.google.com/p/google-app-engine-django/. funciona prácticamente igual que Django solo que los modelos hay que crearlos de forma diferente.

Mi intención no es crear un tutorial de como usar Django en GAE, sino que voy a enlazar a github un par de ejemplos que estoy haciendo. Para mi, lo mejor siempre es ver código y analizar lo que hace. Si no se tiene ningún conocimiento ni de GAE ni de Django, recomiendo primero realizar los siguientes tutoriales.

https://docs.djangoproject.com/en/dev/intro/tutorial01/
http://code.google.com/intl/es/appengine/docs/python/gettingstarted/

Ejemplos

El primero es una aplicación de lo más simple. Es el primer ejemplo que he hecho con GAE + Django. Es un libro de visitas lo más simple posible. Me parece importante que el primer ejemplo sea muy simple para poder entenderlo sin problemas, luego, añadir funcionalidades será más fácil.

[GITHUB]: https://github.com/pablito80/testgaedjg
[APPSPOT]: http://app-pablog.appspot.com/guestbook/  (Si entras, déjame algún comentario.)

El otro es un poco más complicado, es mi página personal aunque tampoco es nada del otro mundo.
[GITHUB]: https://github.com/pablito80/pablovieytes-app
[APPSPOT]: http://pablovieytes-app.appspot.com/ o http://www.pablovieytes.com


Si vas a usar alguna de mis pruebas, asegurate de cambiar el nombre de la app en el fichero "app.yaml"
 y el código secreto de Django en "settings.py".


Para que funcionen correctamente es necesario usar python 2.6 y Django 1.1 ya que es lo que usa GAE, lo suyo es crearse un entrono virtual con estas características.

Ejemplo de como crear un virtualenv en Ubuntu.

Si no se tiene Python 2.6 hay que instalarlo
sudo aptitude install python2.6

crear el entorno virtual con python 2.6
virtualenv --no-site-packages --python=python2.6 GAEVENV


activamos el virtualenv:
source GAEVENV/bin/activate

instalamos Django1.1 en el virtualenv que hemos creado:
pip install Django==1.1

Para comprobar que todo está correcto ejecutar el siguiente comando
pip freeze

El resultado tiene que incluir Django==1.1


Paso a paso

Vamos a ver paso a paso como se ejecutaría en local el primer ejemplo.

clonamos el proyecto:
git clone git@github.com:pablito80/testgaedjg.git

Entramos en el directorio del proyecto
cd testgaedjg

Copiamos el contenido del sdk de GAE en el directorio del proyecto dentro del directorio .google_appengine.

El árbol del directorio del proyecto quedará más o menos así:

testgaedjg
├── appengine_django
│   ├── auth
│   ├── ...
├── .google_appengine
│   ├── appcfg.py
│   ├──BUGS
│   ├──...
├── app.yaml
├── guestbook
│   ├── __init__.py
│   ├── ...
├── __init__.py
├── main.py
├── manage.py
├── readme.md
├── requirements.txt
├── settings.py
├── templates
│   ├── base.html
│   ├── guestbook
│   │   └── guestbook.html
│   └── home.html
├── urls.py
└── views.py

Para iniciar el servidor de pruebas en local, se inicia de la misma manera que Django. Hay que tener activado el virtualenv.
source path/del/virtualenv/bin/activate
python manage.py runserver

y la página estará disponible en:

Si vas a hacer corta y pega con alguno de mis ejemplos, acuerdate de cambiar el nombre de la aplicación y el código secreto.

Yo utilizo el siguiente comando desde el directorio del proyecto para actualizar la aplicación en los servidores de google:

.google_appengine/appcfg.py update . 

martes, 21 de junio de 2011

[Notas Erlang] Unbounding Variables

Erlang es un lenguaje de asignación única por lo que una variable no puede cambiar su valor. Cuando se asigna un valor a una variable, este valor es difinitivo.

Se puede eliminar la relación entre una variable y su valor, a esto se le llama unbounding. No se debe usar esta función cuando se está programando, yo sólo lo uso cuando estoy haciendo pruebas con la consola y no quiero tener un gran número de variables que representen lo mismo.

Para realizar el unbounding se usa la funcion f().
f() realiza el unbounding de todas la variables; pero si se le pasa una variable como parámetro, sólamente hará el unbounding sobre esa variable.

1> A = 1.
1
2> B = 2.
2
3> A.
1
4> f(A).
ok
5> A.
* 1: variable 'A' is unbound
6> B.
2
7> f().
ok
8> B.
* 1: variable 'B' is unbound

Empezando con Erlang

Para un nuevo producto que estamos desarrollando en Openshine, vamos a necesitar desarrollar un servidor. Hemos estado viendo que tecnologías nos podrían servir y al final nos hemos decantado por Erlang. Por lo que ahora estoy aprendiendo a programar con este lenguaje.

Erlang es un lenguaje funcional, es bastante diferente a lo que he visto hasta ahora. Lo que más choca al principio es la asignación única de variables. Variables que no pueden variar.

A continuación pongo unas cuantas fuentes que me están siendo de utilidad para profundizar en el tema:

http://www.erlang.org/doc/getting_started/users_guide.html
http://learnyousomeerlang.com/content

y principalmente el libro "Programming Erlang" de Pragmatic. Yo tengo la versión impresa pero he podido comprobar que está por la red en descarga directa.

En delicious voy almacenando todos los enlaces que encuentro y considero interesantes:

http://www.delicious.com/pvieytes/erlang

No voy a crear una serie completa de posts sobre Erlang y ni mucho menos un tutorial, por la red los hay muy buenos, pero lo que si tengo intención de hacer es ir publicando pequeñas "notas" con trucos o funcionalidades, básicamente a modo de recordatorio.

miércoles, 18 de mayo de 2011

Parsing Twitter's User Timeline with Python

Usually, when you want to include the tweets on a web, it is common to embed a javascript code to show it. Twitter offers a very useful widget for this purpose. http://twitter.com/about/resources/widgets/

This is the best way to show the user timeline without worries. You just copy and paste some javascript code, but sometimes you need more flexibility and copy and paste javascript widget it's not enough.

In this post you'll find a way to parse the Twitter's user timeline from a json file with Python. There are a lot of ways to do that, here's mine.

This is not a Python wrapper arround the twitter api, if you are looking for something like that, please visit http://code.google.com/p/python-twitter/

Getting the Twitter's user time

To download the last tweets, I use the GET statuses/user_timeline function that returns a json file. I've created a function to download the json file and  parse it. I've also created a Tweet class to store the tweet info.

The "read_tweets()" function parse the json file and store the tweet info in a list of Tweet instances. The Tweet class also provide some methods to store info easly.

Let's see the code.



In "read_tweets()" I use urllib2 to read the file and simplejson to parse it. To store the info I use the Tweet Class methods.




The most important Tweet class method is "set_text()". It converts plain text into html code with http, user and hashtag links. I use python regular expressions to find, http://xxx, https://xxx, #xxx and @xxx and replace it for a valid Twitter link.

Django advice

If you gonna use this code with Django, please, let me give you some advice.

"read_tweets()" download a json file every time you call it so please don't use it in a view. It'll delay the view too much. The tweets must be stored with "read_tweets()" and the view must read this stored tweets. You can store the tweets in a lot ways. I use a "manage.py" script added to cron to stored it in memcache, but It's your choice.

If you gonna show the html code stored en Tweet.html_text in a Django template don't forget use the safe tag.

[python]{{ tweet.html_text|safe }}[/python]

martes, 3 de mayo de 2011

Actualizar la Lista de Workspaces Recientes en Eclipse

Cuando se cambia de workspace en Eclipse, aparece una lista con los últimos workspaces con los que has trabajado. Aunque estos workspaces se hayan borrado del disco duro, la lista no se actualiza, y puede aparecer alguno que ya no existe. Para modificar esta lista, es necesario editar el fichero 'org.eclipse.ui.ide.prefs'


 En mi Ubuntu, este fichero se encuentra en ~/.eclipse/org.eclipse.platform_3.5.0_155965261/configuration/.settings/org.eclipse.ui.ide.prefs

Hay que modificar "RECENT_WORKSPACES"

miércoles, 20 de abril de 2011

Añadir Twitter a una página web

He estado buscando como añadir los tweets a una página que estoy desarrollando. Por la red hay varios posts que describen como con unas pocas líneas de javascript puedes añadir los tweets a tu web.





Este es un ejemplo que he probado en una página en Django que estoy haciendo. Hay un par de parámetros que están puestos como variables de los templates de Django que habría que cambiar para que funcionase correctamente:
  • {{ twitter_user }}: nombre de usuario de twitter del cual se quieren visualizar los tweets
  • {{ num_tweets }}:número de tweets que se muestran.

Además, Twitter nos proporciona una página donde podemos crear widgets para nuestra web. Por ejemplo, para este blog, yo me he decantado por este método.

http://twitter.com/about/resources/widgets/

Este es el código que se ha generado para mostrar mis tweets en este blog.



Y este el resultado:


sábado, 16 de abril de 2011

Convertir VÍdeos *.mts

Hace poco he adquirido una cámara JVC-HD. No tenía muy claro si necesitaba que fuese HD, pero un amigo que trabaja editando vídeo, entre otras cosas, me recomendó que mejor que fuese de alta calidad. Si en algún momento quiero hacer algo un poco más profesional, el HD me ofrecerá muchas más posibilidades.
El problema, en cambio, lo tengo ahora que mi intención es visualizar, almacenar y hacer pequeños montajes de videos caseros. El formato de salida de los archivos es *.mts y trabajar con este formato no es muy cómodo. En mi máquina habitual utilizo ubuntu (11.04 en el momento de escribir el post) y mediante el reprductor VLC puedo visualizar los vídeos (este visualizador GNU también se puede usar en MAC OS) pero la calidad no es muy buena, aparecen líneas horizontales. He decidido convertir estos vídeos a un formato más comprimido y, a ser posible, más estandar. Esto me permite visualizar los vídeos sin problemas y realizar ediciones caseras.


Para convertir los vídeos, uso winff. Esta en los repos por lo que la instalación es muy simple.

$ sudo aptitude install winff

Es bastante fácil de usar. Se eligen los archivos con el botón "añadir", el tipo de conversión y el directorio donde se almacenan los ficheros creados.


En mi caso he añadido el parámetro de la relación de aspecto, por defecto pasa los vídeos a 4:3. Mis videos originales estaban grabados a 16:9 por lo que se no se pone este parámetro, aparecen deformados.

Todavía no he visto con que programa voy a editar los vídeos, en un principio había pensado hacerlo con mi mac con imovies, pero sigo teniendo problemas al importar los archivos. Creo que voy a optar por una version libre en Ubuntu. He echado un ojo a OpenShot y tiene muy buena pinta. Además, en su momento usé PiTiVi que también puede ser otra opción.

domingo, 27 de febrero de 2011

crear entornos virtuales de python con virtualenv

Virtualenv nos permite crear entornos virtuales de python. Es decir, nos permite crear entornos con diferentes dependendencias instaladas. Podemos trabajar con diferentes proyectos en un misma máquina que requieran diferentes versiones del mismo paquete.

Para instalar y gestionar dichos paquetes usamos la herramienta pip. Para poder instalar pip, es necesario tener instalado easy_install. Si todavía no has instalado easy_install, hay que ejecutar el siguiente comando.

$ sudo apt-get install python-setuptools python-dev build-essential


Instalación de pip y virtualenv.

$ sudo easy_install pip
$ pip install -U virtualenv

El parámetro -U indica upgrade, lo que quiere decir que se instalará la última versión del paquete indicado.

El entorno virtual se crea sobre un directorio. En el siguiente ejemplo, se crea el directorio env.


$ virtualenv --no-site-packages env

El parámetro '--no-site-packages'  indica que no se instale ningún paquete de los que están instalados en la máquina.


Yolk es una herramienta que permite listar los paquetes instalados en un entorno virtual. Para instalar un paquete en un entorno virtual, se realiza mediante el comando pip pasándole como parámetro -E y el directorio del entorno virtual.

$ pip install -E env yolk



La herramienta yolk muestra los paquetes instalados. Pero para poder utilizarla, es necesario activar el entorno virtual. Para activarlo hay que ejecutar el siguiente comando:


$ source env/bin/activate
$ yolk -l
pip - 0.7.2 - active
setuptools - 0.6c11 - active
wsgiref - 0.1.2 - active development (/usr/lib/python2.6)
yolk - 0.4.1 - active


El comando "pip freeze" también muestra los paquetes instalados.


$ pip freeze
wsgiref==0.1.2
yolk==0.4.1


Para desactivar en entorno ejecutamos deactivate


$ deactivate

Para crear un fichero que contenga los requerimientos del entorno virtual ejecutamos el siguiente comando.


$ pip freeze -E env > requirements.txt

Etos requerimientos se pueden instalar mediante pip. http://pip.openplans.org/#requirements-files

sábado, 26 de febrero de 2011

Borrar la barra del blogger

Por defecto, los blogs creados en blogger tienen una barra de navegación dentro de blogger. Nos permite "loggearnos", ir al siguiente, blog.

Si no te gusta que esté presente esta barra, es posible eliminarla. Realmente, lo que se hace es modificar el template del blog para ocultarla. Veámos como:

Lo primero que hay que hacer, es is a la pestaña de diseño la página de administración del blog. Después, a la siguiente pestaña. Edición de HTML.

Nos sale una vista con el código de la plantilla. Si no estás acostumbrado/a a trabajar con código, no te preocupes, lo que hay que hacer es muy fácil. De todas maneras, siempre es mejor guardar un copia de la plantilla antes de modificar nada. Para guardar la plantilla actual hay un enlace "Descargar plantilla completa" que nos permitirá almacenar la plantilla en nuestro disco duro.


A continuación hay que buscar en el código el siguiente texto(sin el espacio enre "<" y "/"):
]]>< /b:skin>


y justo encima de dicho texto copiar

#navbar-iframe {
opacity:0.0;
filter:alpha(Opacity=0)
}

miércoles, 27 de octubre de 2010

Nota Django: sobreescribiendo métodos

http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods

En el ejemplo siguiente se muestra como sobreescribir el método save() de un modelo. Lo importante es poder añadir más código al función pero sin perder la funcionalidad primitiva.


class Model(models.Model):
pass

def save(self, *args, **kwargs):
#add some functionality
super(Model, self).save(*args, **kwargs) # Call the "real" save() method.
#add some functionality

martes, 21 de septiembre de 2010

Nota python: Eliminar elementos repetidos de una lista

Necesitaba eliminar elementos repetidos de una lista, la primera aproximación sería recorrer la lista e ir comprobando si los elementos están repetidos. Decidí buscar otras opciones y he encontrado dos formas de eliminar elementos repetidos de una lista. Ninguno de estas dos formas respeta el orden inicial de la lista.

Uso del tipo de dato set (conjunto de datos mutable, sin orden, que no contiene duplicados). Convertimos primero la lista a tipo set y luego volvemos a convertir el tipo set en lista.

>>>lst = [1, 1, 3, 2]
>>> lst
[1, 1, 3, 2]
>>> lst = list(set(lst))
>>> lst
[1, 2, 3]

En el siguiente ejemplo hacemos uso de los diccionarios para eliminar los elementos repetidos. Primero creamos un diccionrio donde las claves están almacenadas en la lista. Depués obtenemos las claves del diccionario que acabamos de crear.

>>> lst = [1, 1, 3, 2]
>>> lst
[1, 1, 3, 2]
>>> lst = dict.fromkeys(lst)
>>> lst
{1: None, 2: None, 3: None}
>>> lst = lst.keys()
>>> lst
[1, 2, 3]

jueves, 9 de septiembre de 2010

Nota: Trabajando con listas en Python. Igualar listas.

Estaba depurando un programa y me he dado cuenta de como funcionan las listas en python al igualarse.
Si se iguala una lista a otra, no se está creando una nueva lista con los valores de la anterior, si no que estás creando un nuevo nombre para la misma lista.

Voy a poner un ejemplo donde se ve claramente:

l1 = []
l1.append('1')
l1.append('2')
l2 = l1
l2.append('3')
print l1
>> ['1', '2', '3']

martes, 24 de agosto de 2010

Django: hosting gratuito

Desde www.alwaysdata.com nos ofrecen la posibilidad de crearnos una cuenta gratuita que nos ofrece servicio de hosting para nuestros proyectos en django.
La página de registro está en francés pero una vez dado de alta como usuario, el panel de administración está en español.

Todavía no he podido configurar el servidor para hacer alguna prueba pero parece que tiene buena pinta. Tenía ganas de encontrar un servicio de hosting gratuito para django.

En cuanto haya subido algo al servidor, ya os comentaré.

http://www.alwaysdata.com

PD: Si alguien lo prueba, no estaría mal que lo compartiese en la zona de comentarios.

lunes, 23 de agosto de 2010

Django: Restaurar una tabla borrada a mano de una aplicación gestionada con South

Estaba haciendo unas pruebas con la base de datos y necesitaba limpiar una tabla, por error, en vez de borrar el contenido, eliminé la tabla de la base de datos.

Si se intenta migrar la aplicación, South no restaura la tabla, ya que no se comprueba si las tablas están creadas en la base de datos. Si por el contrario, al ejecutar el comando "python manage.py syncdb", tampoco crea la tabla ya que detecta la tabla está gestionada por south. Para poder generar la tabla, se hace con el comando syncdb, pero además hay que incluir el parámetro -all.
python manage.py syncdb -all

Gestor de paquetes easy_insatall

wikipedia:

EasyInstall es un gestor de paquetes para el lenguaje de programación Python que suministra un formato estándar para distribuir programas y librerías en Python, basado en el envoltorio llamado huevos de Python (Python eggs).

Para poder usar easy_isntall, es necesario instalar python-supertools.
apt-get install python-setuptools

Una vez que ya tenemos instalado python-supertools, ya se pueden instalar los "eggs" con easy_install.

Ejemplo de instalación:
easy_install PackageName


Ejemplo de desinstalación:

easy_install -m PackageName



Nota:
Es muy interesante el uso de easy_install con virtualenv. A ver si hago un pequeño post sobre el uso de virtualenvs.

Borrar el historial de South.

Para reiniciar completamente el historial de South hay que hacer lo siguiente:
python manage.py migrate appname --fake zero

Este comando borra todo el historial de South.

A continuación se tienen que borrar los ficheros.
rm appname/migrations/*

En este momento ya tenemos el historial de South completamente limpio por lo que es necesario crear las nuevas migraciones:
python manage.py schemamigration appname --initial
python manage.py migrate appname

Si solamente queremos borrar el historial hasta un lugar concreto, hay que hacer lo siguiente:
python manage.py migrate appname --fake MIGRATION_NUMBER

El atributo --fake, indica que solamente se borran las migraciones de la base de datos, no afecta a lo que contiene la base de datos, es decir, no se aplican los cambios.

A continuación hay que borrar todos los archivos posteriores a la migración desde la que queremos partir que se encuentran en :
appname/migrations

A continuación creamos una nueva migración para guardar los cambios que hay en la base de datos. Al haber hecho "python manage.py migrate appname --fake MIGRATION_NUMBER", simplemente se han borrado las migraciones de la base de datos pero no se han aplicado los cambios, ahora lo que nos indica South y lo que hay en la base de datos es diferente por lo que es necesario hacer una nueva migración:
python manage.py schemamigration appname --auto

El siguiente paso que debemos hacer, es aplicar la migración:
python manage.py migrate appname