Etiqueta: tutorial

Recargar el navegador desde Emacs

Aunque Emacs no suele aparecer entre los editores preferidos para desarrollo web sigue teniendo opciones que lo hacen interesante.

En este artículo vamos a comentar algunos «plugins» que nos ayudan a recargar el navegador automáticamente cuando hacemos cambios en el código. No todos funcionan en las últimas versiones de Emacs, pero los dejo en el artículo para saber lo que hay disponible, o al menos lo que no merece la pena probar.

Conclusiones

Para quien quiera ir directo al grano el que me parece más recomendable en este momento es Mini Kite Mode, que se comenta al final de listado y que descubrí a través de esta pregunta de stackoverlow. En las respuestas se mencionan algunos complementos para emacs para trabajar con desarrollo web que no he probado y que también podrían ser interesantes pero están todos desactualizados.

Listado de plugins

Impatient Mode

Uno de los limitantes de Impatient Mode es que hay que habilitar el impatient-mode por cada uno de los buffers que se quieran observar. Aunque supongo que se puede configurar de algún modo algún hook para que automáticamente habilite la observación en los buffers abiertos con determinadas extensiones.

Tras habilitar el modo M-x impatient-mode y lanzar el servidor M-x httpd-start tendremos en localhost un navegador que escuche los cambios http://localhost:8080/imp/

Otro de sus problemas es que lo que parece hacer, es cargar dentro de un iframe la web que estamos editando en emacs, y desde el código html/js en el que está empotrado el frame se hace un pooling cada cierto tiempo para ver si el contenido cambia y recargar. Empotrar tu código dentro de un iframe al final excepto para casos sencillos puede ser problemático y el sistema de pooling tampoco es muy efectivo en la práctica, porque cada pocas pulsaciones de teclas se hace un refresco de la página.

Skewer Mode

Para hacer funcionar Skewer Mode seguramente haya que hacer un par de pruebas, pero hay un vídeo y una pregunta de stackexchange que pueden ayudar.

La parte interesante de este modo es que permite abrir un buffer en modo REPL para javascript. De modo que podemos evaluar el código js directamente en emacs como si estuvieramos usando la consola del navegador. O podemos editar nuestra fuente javascript y relanzar una función o porciones de código al navegador.

Uno de los mayores limitante es que la recarga no es automática, y en el modo html funciona tag a tag. Es decir, no podemos reenviar el buffer entero al navegador, si no sólo los tags que nos interesen. Lo que hace es modificar el dom, para actulizar el contenido de los tags. No lo he encontrado especialmente cómodo, pero tiene algunas extensiones que podrían simplificar el trabajo como skewer-less o skewer-reload-stylesheets.

Emacs browser refresh

Browser refresh es una idea sencilla e interesante. Basicamente usa xdotool, una herramienta que permite scriptear movimiento de ratón y pulsaciones de teclas, para poner la ventana del navegador en foco y pulsar «F5», cuando le damos a salvar. El script original no funciona del todo bien, y aunque es fácil de arreglar es una solución «error prone». Si tenemos varias ventanas del navegador abiertas, o hemos cambiado de pestaña puede funcionar incorrectamente.

GC Refresh Mode

De nuevo una buena idea pero el código de GC Refresh Mode está desactualizado y no funciona. Al activar el modo M-x gc-refresh-mode pregunta la url a recargar, que puede ser un http://localhost o un file:///, abre esa uri en chrome en modo remote-debugging y sobreescribe C-x C-s para que al recargar se ejecute un script en python. El script en python es una implementación muy sencilla del Chrome Debugging Protocol que conecta a un socket con el que comunicarse con la instancia del navegador que abrió antes, busca la pestaña donde está la uri de interés y la recarga.

El problema es que Chrome ya no usa exactamente este sistema y el script no funciona. Este plugin está inspirado en la página de Save And Reload Browser del Emacs Wiki.

chrome-reload-page

Basándose en la idea de GC Refresh Mode hace algún tiempo escribí un ejemplo de código (funcional) que acabó de subir a github.

Este script usa el Chrome debugging protocol para recargar la pestaña. El script lleva empotrado el código de python del fork de max-weller de chrome_remote_shell para ahorrar trabajo.

Mini Kite Mode

Mini Kite Mode es la más funcional de las opciones de este artículo.

Se puede instalar directamente desde MELPA. Para usarlo añadiremos a nuestro .emacs, las siguientes líneas.

(require 'kite-mini)
(require 'kite-mini-console)
# Automatically Turn on the mode for your buffer of choice.
(add-hook 'js-mode-hook (lambda () (kite-mini-mode t)))
(add-hook 'css-mode-hook (lambda () (kite-mini-mode t)))
(add-hook 'html-mode-hook (lambda () (kite-mini-mode t)))

El segundo require sólo es necesario si queremos abrir un buffer de Emacs como una consola js en modo REPL (similar a la consola de DevTools). Y los hooks permiten activar el modo para los buffers de interés en tener que activarlo a mano M-x kite-mini-mode

Una vez en un buffer (y través a ver lanzado chrome / chromium en modo remote debug) simplemente conectamos con

M-x kite-mini-connect

Si la pestaña que tenemos abierta es con la que queremos interactual podemos simplemente pulsar intro. A partir de ese momento podemos lanzar la consola de js, enviar una región al navegador para que sea evaluada, o recargar la pestaña.

El mayor problema, de esta herramienta, y en realidad de todas las que usen el Remote Debug, es que sóla una herramienta puede estar conectada mediante el protocolo a la vez, y las DevTools hace uso de este sistema también. De modo que si kite está conectado y se abren las DevTools kite se desconectará. Y si son las DevTools las que estan activadas cuando hacemos kite-mini-connect, kite no llegará a conectar.

Para simplificar un poco el flujo he editado el fichero de ~/.emacs.d/elpa/kite-mini-20160508.406/kite-mini-el para que antes de hacer el reload salve el buffer, quedando así

(defun kite-mini-reload ()
(interactive)
(save-buffer)
(kite-mini-call-rpc
"Page.reload"
(list :ignoreCache t)))

De este modo al pulsar C-c C-r, primero salva y luego recarga. El siguiente paso, sería que mientras esté conectado, pulsar C-x C-s salve el buffer y recargue, pero por ahora con esto me llega.

Usando GeoProcesos en gvSIG desde Java

La semana pasada había un correo en la lista de desarrollo de gvSIG preguntando como poder lanzar geoprocesos desde tu propio plugin mediante Java. Tras una pequeña investigación he escrito un código de ejemplo que espero que sea útil a quien tenga esta necesidad.

Descargar el código

A mi particularme me gusta descargar el código fuente de las partes de gvSIG con las que voy a trabajar. Esto simplifica el usar las herramientas del IDE para saber como usarlo, encontrar errores, y revisar los tests, en caso de haberlos, para tener pistas de como escribir mi propio código.

Para ello primero se mira la versión del plugin que se corresponda con la versión de gvSIG que estás usando. Creo que lo más fácil es descargar una versión portable de gvSIG. Entrar a la carpeta que contiene el plugin, en este caso org.gvsig.geoprocess.app.mainplugin y abrir el fichero package.info. En la property version está el tag del repo correspondiente a esa versión. Por ejemplo para la 2.3RC2 sería el 2.266. Por tanto para descargar el repo haremos:


svn checkout http://devel.gvsig.org/svn/gvsig-geoprocess/org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.66/

A continuación,e n caso de usar Eclipse, iremos a import -> Existing maven projects, e importaremos la raíz del nuevo plugin descargado.

Añadir las dependencias

Al desarrollar en gvSIG debemos tener en cuenta que las dependencias de nuestro plugin, por decirlo de algún modo, serán de dos tipos. En «Tiempo de desarrollo», y en «Tiempo de ejecución». Las dependencias en desarrollo se definen en el pom del proyecto permitiéndonos definir el classpath de desarrollo para trabajar con las clases que nos hagan falta.

En ejecución, cuando estamos probando o ejecutando gvSIG, el classpath se define de manera dinámica por decirlo de algún modo en el fichero de config.xml. gvSIG buscará entre las dependencias que hayamos definido en el config las clases que se pueden usar en nuestro plugin.

Para que quede claro, a nuestro pom se añadirán otros proyectos maven. A nuestro config se añadirán plugins de gvSIG.

Por ejemplo para el caso de usar los geoprocesos, añadiremos al pom:



org.gvsig
org.gvsig.geoprocess.lib.api
2.2.66


org.gvsig
org.gvsig.geoprocess.lib.sextante
2.2.66

y al config



Obtener el algoritmo que queremos

Esta una de las partes en las que tengo más dudas que esté correcta.

En general accederemos a las funcionalidades de gvSIG a través de un Locator que nos dará un Manager que nos dará la funcionalidad. En el caso de los geoprocesos sería:


String ALG_NAME = "gvSIG-intersection";
SextanteGeoProcessManager manager = (SextanteGeoProcessManager) GeoProcessLocator.getGeoProcessManager();
HashMap algs = manager.getAlgorithms();
GeoAlgorithm alg = algs.get(ALG_NAME);

Debemos castear a la implementación por defecto del manager SextanteGeoProcessManager porque la interfaz en sí no proporciona el método getAlgorithms. Esto diría que es un bug.

La forma de obtener ALG_NAME, no estoy seguro de cual es. En principio lo más fácil sería poner un breakpoint y mirar los valores de algs. Aunque en mi caso sólo salen los propios de gvSIG y no los de Sextante.

Seteando valores al algoritmo

Todos los algoritmos definen un método defineCharacteristics que nos indican los valores que recibe, tanto de entrada como de salida. Esta definición de valores se obtiene a través del método getParameters

En nuestro código debemos obtener cada uno de los parámetros necesarios y setear su valor real para nuestro caso. Por ejemplo:


private void setParams(GeoAlgorithm alg) throws WrongParameterIDException {
ParametersSet params = alg.getParameters();

FLyrVect interLyr = getLayer("inter");
FlyrVectIVectorLayer inter = new FlyrVectIVectorLayer();
inter.create(interLyr);

FLyrVect layerLyr = getLayer("layer");
FlyrVectIVectorLayer layer = new FlyrVectIVectorLayer();
layer.create(layerLyr);

params.getParameter(IntersectionAlgorithm.INTER).setParameterValue(
inter);
params.getParameter(IntersectionAlgorithm.LAYER).setParameterValue(
layer);
params.getParameter(IntersectionAlgorithm.SELECTGEOM_INPUT)
.setParameterValue(false);
params.getParameter(IntersectionAlgorithm.SELECTGEOM_OVERLAY)
.setParameterValue(false);
}

En este caso para no escribir a mano los idenfificadores de los parámetros uso las variables estáticas definidas en el propio algoritmo. Eso hace que haya que añadir al pom el algortimo:



org.gvsig
org.gvsig.geoprocess.algorithm.intersection
2.2.66

Para las capas de entrada al algoritmo hay que generar una FlyrVectIVectorLayer. Como se muestra en el código de ejemplo lo más sencillo es obtener un FLyrVect y construirla con el create.

Ejecutando el algoritmo

Los algoritmos se lanzan mediante el método execute que como indica la documentación admite hasta tres parámetros.

  • ITaskMonitor task. Que puede ser nulo y permite monitorizar el estado para por ejemplo poner una barra de progreso al usuario
  • HashMap outputMap. Que permite modificar los nombres que sextante asigna a los parámetros de salida (en general capas)
  • OutputFactory outputFactory. Define como se crearán los objetos de salida. Puede ser nuestra propia implementación o usar la factoría por defecto

Por tanto ejecutarlo sería simplemente:


alg.execute(null, new DefaultOutputFactory(), null);

Obteniendo los resultados

Con la factoría por defecto las capas se crean en un directorio temporal que en linux es /tmp/tmp-andami y les asigna nombres aleatorios (creo que basados en el timestamp). Supongo que habrá alguna utilidad que nos permite ejecutar una especie de FinalActions para añdirlos automáticamente a la vista. O implementando nuestra propia OutputFactory podríamos definir otras rutas. También diría que podemos prescindir del OutputFactory y lanzar el algoritmo mediante processAlgorithm si igual que hicimos con los parámetros de entrada seteamos adecuadamente los valores de salida, especialmente el OutputChannel de las capas.

En todo caso el método getOutputObjects nos devuelve los objetos de salida, así por ejemplo podríamos llegar el FlyrVectIVectorLayer de la capa de polígonos de salida con:


OutputObjectsSet outputSet = alg.getOutputObjects();
OutPut output = outputSet.getOutPut(IntersectionAlgorithm.RESULT_POL)
FlyrVectIVectorLayer result_pol = (FlyrVectIVectorLayer) output.getOutputObject();

Video: Aplicaciones en tiempo real con python y postgres

Una charla de como montar aplicaciones en tiempo real con python y postgres. Tiempo real entendido como notificaciones de un chat, hacer algo cada vez que se actulice una tabla de la bd etc,…

El vídeo se hace un poco largo, seguramente con las transparencias llegaba para hacerse una idea general. Pero aún así se hace interesante por alguna de las técnicas que emplea:

  • Aboga por no usar frameworks en python. Con las librerías de hoy en día es sencillo montar una API Rest gestionando las llamadas de bajo nivel directamente
  • Usa las funciones de postgres de LISTEN y NOTIFY que combinadas con un trigger permiten que código cliente (psycopg2) sean notificados cuando algo pasa en la base de datos (se modifica una fila o lo que sea) y actuén en consecuencia (provocar un cambio en el navegador mediante websockets)
  • Para simplificar la API y el diseño de la bd, los datos se guardan como tipos nativos postgres (varchar, boolean,…), y se usa la función de postgres row_to_json para recuperarlos una cadena de texto con formato json.
  • Usa httpie para probar la API Rest. Si alguna vez usaste curl para esto enseguida verás que está bien conocer httpie.
  • A pesar de que la idea principal de la charla es montar una aplicación en tiempo real con el mínimo número de dependencias (complejidad) el proceso de build que monta no parece trivial. pip para dependencias en python, nodeenv (una especie de entorno virtual para node que se integra con el virtualenv de python), bower para las dependencias javascript de cliente,… Todo ello orquestrado por un Makefile.
  • No muestra como hacer la parte del frontend, pero en todo caso el código está en su repo

Compilando y depurando un plugin de ejemplo para gvSIG 2.1 desde Eclipse

Joaquín del Cerro ha publicado un artículo explicando como compilar y depurar un plugin de ejemplo para gvSIG 2.1 con NeatBeans. He adaptado sus instrucciones para Eclipse que es mi IDE habitual. Este artículo no es tan detallado como el suyo así que seguramente tendrás que consultar los dos, especialmente los pasos previos que comenta Joaquín para que todo funcione.

Una vez que tenemos los «previos» realizados, creamos un nuevo workspace en eclipse, por ejemplo workspace-gvsig-landregistry.

Nos aseguramos de que tenemos instalados en eclipse:

Abrimos la perspectiva de eclipse de SVN Repository Exploring, desde Window -> Open perspective -> Other, o cualquier otro de los sitios desde los que se puede abrir.

Y añadimos el repositorio del plugin desde File -> New -> Repository Location o el icono correspondiente. Como URL usaremos:

http://devel.gvsig.org/svn/gvsig-plugintemplates/org.gvsig.landregistryviewer/trunk/org.gvsig.landregistryviewer/

Seleccionamos el repositorio que acabamos de añadir y en el menú contextual escogemos Check out as maven project

Si no tenemos el conector de maven-svn instalado, nos pedirá instalarlo. En la ventana previa al checkout nos aseguraremos de que la opción «All projects» está activada

Puede tardar un ratito en descargar, sobre todo si tiene que descargar muchas dependencias. Cuando acabe, pasamos a la perspectiva Java y ya tendremos los proyectos correspondientes al plugin configurados en el workspace.

Si no tienes la opción de Build automatically activada, haz un build all. A continuación pon un punto de ruptura para comprobar que todo funciona correctamente en el punto que indica Joaquín (método createWindow de la clase LandRegistryViewerExtension).

Tras lanzar gvSIG en modo debug,


./gvSIG --debug --pause

configuramos el debugger. En Debug Configurations, añadiremos una nueva configuración del tipo Remote Java Application

En name pondremos lo que queramos, por ejemplo org.gvsig.landregistryviewer.app, en project org.gvsig.landregistryviewer.app.mainplugin y en port 8765. Si antes de crear la configuración de debug seleccionamos el proyecto org.gvsig.landregistryviewer.app.mainplugin en el package explorer nos rellenará automáticamente name y project.

Al darle a debug debería abrirse gvSIG y pararse la ejecución en el punto que hemos marcado.

Tutorial básico de django south

South es una app de django que permite modificar la estructura de la base de datos de una aplicación django cuando cambiamos el modelo (models.py).

El comando syncdb sólo crea nuevas tablas, pero no modifica tablas existentes, así que si en el modelo de una aplicación renombramos un campo de una tabla existente syncdb no realizará ese cambio en la base de datos. A este tipo de cambios en la base de datos se les denomina «migración del esquema» y es de lo que se encarga South.

Instalación

  1. pip install south
  2. Agregar «south» a INSTALLED_APPS
  3. Ejecutar syncdb antes de crear nuestros propios modelos. Está será la última (y única) vez, que necesitamos ejecutar este comando
    manage.py syncdb

Usar south en un una app nueva

  1.  Crear la aplicación, y empezar a rellenar el models.py
  2. Crear el script de migración inicial
    python manage.py schemamigration app_name --initial
  3. Hacer los cambios en la bbdd
    python manage.py migrate app_name

Usar south en una app ya creada

python manage.py convert_to_south app_name

En el caso de que haya otros desarrolladores en el equipo y cada cual esté usando su propia instancia de la base de datos, el resto de desarrolladores deberá migrar la primera versión en modo fake,
python manage.py migrate app_name 0001 --fake

el resto normal, así:
python manage.py migrate app_name

De lo contrario no podrán migrar su versión de la base de datos.

Migración de modelos

  1. Modificamos el models.py de nuestra aplicación
  2. Crear un nuevo script de migración
    python manage.py schemamigration app_name --auto
  3. Aplicar la migración a la bbdd
    python manage.py migrate app_name

Como funciona

Se puede decir que South funciona en varios niveles de abstracción disintos.

  • Añade una tabla en la base de datos que mantiene el estado actual de la base de datos. Es decir, guarda que migraciones se han aplicado.
  • Crea un directorio en la applicación, donde guarda para cada migración un fichero (script) con la información necesaria para realizarla
  • Añade varios comandos al manage.py

Los ficheros de migración generados en deben subirse al repositorio para que el resto de los desarrolladores pueda también realizar la migración.

Referencias

Nota: Editado el 7/Marzo/2015 para añadir el comentario de Mauricio.

Python Scripting for Students of Remote Sensing

Python Scripting for Students of Remote Sensing es un manual de python orientado a la teledetección. Si no sabes nada de python es mejor empezar por otro manual y luego saltar directamente al capítulo 5, «Plottin». La parte de python en sí es muy básica y no está muy bien explicada. Del capítulo 5 al 10 se muestran algunas librerías interesantes de python para mostrar gráficos (matplotlib), para estadística y calculos científicos (numpy), para procesado de raster (gdal), o ejemplos sencillos de trabajo con datos lidar en ficheros ascii. La información que dan es bastante escueta, pero si ya conoces python en un par de horas puedes leerlo para hacerte una idea de que posibilidades hay en estos campos.

En la misma página se pueden encontrar otros manuales interesantes sobre teledetección.

Descubrí el curso gracias al comentario de José Guerrero.

 

 

 

Um curso objetivo de programação em Python

Gracias al blog de Anderson Medeiros encuentro un interesante tutorial de python escrito en Portugués pero muy facilito de seguir.

Es un tutorial de introducción, rápido de leer y que me ha ayudado a recordar algunos de esos conceptos que por estar más habituado a otros lenguajes tipo Java no empleas a menudo.

Algunas cosillas que he recordado, aprendido o me han gustado.

Listas, tupas y strings

Explica bien que son listas, tuplas, diccionarios y strings. A listas y tuplas se las llama en ocasiones secuencias puesto que sus propiedades son muy parecidas. Una tupla es en realidad una lista inmutable.

Conviene tener en la cabeza lo fácil que es hacer slices (subconjuntos de secuencias) y substrings en python, incluso empleando índices negativos para empezar a contar por el final. LLega con escribir:

>>> lista = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> lista[2:5]
['c', 'd', 'e']
>>> lista[2:]
['c', 'd', 'e', 'f', 'g']
>>> lista[:5]
['a', 'b', 'c', 'd', 'e']
>>> lista[:-2]
['a', 'b', 'c', 'd', 'e']
>>> lista[-2:]
['f', 'g']

Los operadores * y + se pueden usar sobre listas, tuplas y strings. * replica n veces el elemento y + concatena.

Ejemplo para strings:

>>> a = "exato"
>>> print a * 2
exatoexato
>>> print "quase " + a
quase exato

Ejemplo para listas:

>>> a = [-1, 0]
>>> b = [1, 2, 3]
>>> print b * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> print a + b
[-1, 0, 1, 2, 3]

Para chequear si un elemento está contenido en una secuencia o diccionario se usa el operador in

>>> "x" in "cha"
False
>>> 1 in [1,2,3]
True

Combinar de forma implícita operaciones lógicas

Además de los operadores lógicos not, or, and python permite combinar ciertas operaciones lógicas de forma implícita:

Por ejemplo podemos comprobar un número está en un determinado rango de esta forma:

a = 5
if 3 < a < 9:
print "Entre 3 y 9"

a = 3; b = 3; c = 2;
if a == b <= c:
print "a igual a b y b menor o igual que c"

Clausula else en bloques for y while

En los for y los while se puede emplear una claúsula else que se ejecutará cuando se salga del bloque de iteración por haber acabado la secuencia (en lugar de salir por un break)

valores = [2, 4, 5, 2, -1]
for i in valores:
if i < 0:
print "Negativo encontrado: %d" %i
break
else:
print "Nenhum negativo encontrado"

Valores booleanos

No está de más recordar que en python se considera falso a:

  • el booleano False
  • el valor 0 (zero)
  • una lista, diccionario, tupla o string vacios (de tamaño cero)
  • el valor especial None

Así por ejemplo para comprobar si una lista no está vacía mejor que emplear

lista = ['a']
if (len(lista)) != 0:
print "forma poco apropiada de comprobar si una lista no está vacia"

usaremos directamente

if lista:
print "Lista no vacia"

Argumentos de funciones

Existen dos formas de pasar un número variable de argumentos a una función:

def desculpa(alvo, *motivos):
d = "Desculpas %s, mas estou doente" % alvo
for motivo in motivos:
d = d + " e %s" % motivo
return d + "."

>>> desculpa("senhor", "meu gato fugiu",
... "minha tia veio visitar")

o bien

def equipe(diretor, produtor, **atores):
for personagem in atores.keys():
print "%s: %s" % (personagem, atores[personagem])
print "-" * 20
print "Diretor: %s" % diretor
print "Produtor: %s" % produtor

>>> equipe(diretor="Paul Anderson",
... produtor="Paul Anderson",
... Frank="Tom Cruise", Edmund="Pat Healy",
... Linda="Julianne Moore")

Frank: Tom Cruise
Edmund: Pat Healy
Linda: Julianne Moore
--------------------
Diretor: Paul Anderson
Produtor: Paul Anderson

Si tienes algún tutoirial de python que te haya gustado o algún truquillo que quieres compartir deja un comentario.