Publicado el 13 de julio de 2010 | Categoría/s: Python

Un típico uso de un ListCtrl es usarlo para mostrar un Log de la aplicación que muestra mensajes al usuario, similar a lo que puede hacer la barra de estada, pero con la ventaja (complementaria, si se quiere), de mantener un historial de los eventos ocurridos.

En tal caso, primero, hay una decisión de diseño que hacer: ¿los nuevos mensajes se agregan al inicio (como un blog) o al final de la lista (como los comentarios) ?

No sé si existe una respuesta canónica a la cuestión, pero infiriendo (de los pelos) el sentido de lectura occidental (de izquierda a derecha y de arriba hacia abajo) decidí que "un nuevo contenido" debe estar abajo del anterior.

Eso trae aparejado un nuevo problema: si se agrega un nuevo item a ListCtrl al final y ya hay más de los que caben en el espacio visible del control, el último (el más importante) no se verá en pantalla y el usuario debería hacer un scroll hasta el final para verlo. Es decir, para un panel de Log, el scroll vertical siempre debería mantenerse abajo.

Por suerte no hay que liarse con generar eventos programaticamente, ni manipular el scroll, ni obtener dimensiones del widget. He aquí una solución "fits your brain": el método EnsureVisible(index)

Por ejemplo:

    def OnAppendLog(self, msg):
        ico = self.icon_map[msg.data[0]]
        message = msg.data[1]
        index = self.list.InsertImageStringItem(sys.maxint, message, ico)
        self.list.SetStringItem(index, 1, time.strftime('%H:%M:%S'))
        self.list.EnsureVisible(index) #keep scroll at bottom

Al agregar un nuevo mensaje de log, obtenemos el índice y wx nos asegura que la fila con ese índice estará visible en pantalla.

Comentarios (0) | Link

Publicado el 13 de julio de 2010 | Categoría/s: Python

Hace aproximadamente dos meses que estoy trabajando en lo que será mi proyecto final, para recibir el título de ingeniero en computación.

El proyecto es una aplicación de uso "científico y académico" implementada en Python que sirve para obtener diagramas de equilibro termodinámico entre fases fluidas de sistemas binarios. Toda la batahola está en este repo.

En concreto, el proyecto se circunscribe a la generación y [análisis sintáctico] de archivos de texto con el que la aplicación se comunica con los programas que implementan los algoritmos de cálculo, que están implementados en Fortran, y son, literalmente, unas cajas negras. [1]. Se procesan esos archivos para obtener arrays con los que se plotean las distintas curvas.

Utilizo principalmente wxPython, Matplotlib y Numpy. Vale destacar, ya que mucho de un trabajo final es documentación, que escribo en restructuredText, renderizando con Sphinx y el genial rst2pdf

Esta perorata para contar que iré apuntando en este abandonado blog (no más que el otro, y en general, el resto de mi vida) algunos descubrimientos informáticos y de otro tipo, si es que ocurren, en el desarrollo de este proyecto.

Comentarios (0) | Link

Publicado el 10 de mayo de 2010 | Categoría/s: Linux

Esto es una ayuda memoria para mi yo dubitativo del futuro: para hacer funcionar el video de la notebook que es SiS 671/771 en Ubuntu (a partir de la versión 9.10) instalar este paquete y este xorg.conf este xorg.conf.

Para pantalla dual con LCD externo a resolución full 1280x1024

Comentarios (1) | Link

Publicado el 23 de marzo de 2010 | Categoría/s: Python

Python es un gran lenguaje de programación, y como tal se merece la comunidad que tiene, donde expertos y novatos se sienten parte.

Comentarios (1) | Link

Publicado el 11 de diciembre de 2009 |
This is perhaps the most beautiful time in human history;
it is really pregnant with all kinds of creative possibilities made possible
by science and technology which now constitute the slave of man,
if man is not enslaved by it.

Jonas Salk

No sólo de la técnica vive el hombre.

Mi otro blog ganó una mención especial en el concurso El Blogazo del Centro Cultural España-Córdoba, en la categoría literatura. El jurado, entre otros, lo integraban Hernán Casciari y José Playo

Comentarios (0) | Link

Publicado el 2 de diciembre de 2009 | Categoría/s: Python, Empresa

Para los trabajadores online freelance (programadores, diseñadores, traductores, etc) trabajar para el exterior es un objetivo primordial. Aunque en algunos sectores la competencia es leonina y se pauperizan los honorarios, el tipo de cambio del peso respecto a otra monedas fuertes hace que siga siendo muy provechoso.

En traducción, que tiene un sistema de presupuesto lineal basado en cantidad de palabras del texto del idioma origen, es fácil cuantificar la diferencia. En Argentina se cobra entre $0,10 y $0,15 (pesos argentinos) por palabra, mientras que en europa se cobra entre 0.05 € y 0.07€. O sea, se gana hasta el triple por realizar el mismo trabajo.

El problema, al menos desde Argentina, es cobrar. Aquí comparto mi experiencia esperando ayudar a otros.

De Adsense a la billetera

Una forma simple y rápida pero bastante onerosa es Western Union. Es un servicio de transferencias de dinero persona a persona (física o jurídica), con sedes en casi todo el mundo. Tiene dos tipos de servicio: Quick Cash y 24 horas.

Western Union tiene multiples instancias de lucro, que lo vuelven un ser. Se le cobra entre el 2.5 y 5% al emisor (desde Europa a Argentina el límite de transferencia es 500€) y además, el receptor cobra en moneda local a un tipo de cambio definido por WU que siempre está entre un 3 y 6% por debajo del tipo de cambio del dia. Sobre todo los días que hay corridas en suba, el tipo de cambio queda desfasado (tiene una actualización muy lenta) y es un mal momento para cobrar.

Existe una forma de salvar este cargo solapado para el receptor: si el envío es tipo Quick Cash y en dólares estadounidenses, se puede retirar en dólares en los locales Western Union de los supermercados Walmart (que es el representante oficial de WU en Argentina). Este servicio no tiene costo para el receptor.

Esto es muy útil para quienes utilizan Google Adsense en sus sitios web, ya que Google ofrece este servicio de pago. Basta anotar el número de transferencia (MCU) y documento en mano aclarar en Wester Union de Walmart que queremos cobrar en dólares.

Mucho más fácil, rápido y sin perder un sope que pedir el cheque y venderlo en una financiera.

Cobrar del extranjero

Internacionalmente está casi estandarizado el uso de Paypal como medio de pago de honorarios (y casi cualquier otro tipo de transacción en internet) pero este sistema no tiene integración con el sistema bancario argentino lo cual complica la tarea de monetizar los fondos.

Además, un usuario no puede cargar crédito a su cuenta paypal con una tarjeta de crédito, aunque esta sea válida internacionalmente. Un detalle que complica a quienes quieren comprar o donar en el extranjero.

Sin embargo, Paypal sigue siendo interesante para todos los que necesitamos cobrar desde el extranjero. Además de facilitarle la vida al emisor (cliente) que seguramente ya está acostumbrado a este sistema, la transferencia entre cuentas paypal personales no tiene costo. Esto significa que si el cliente tiene una cuenta paypal con fondos (que en la mayoría de los paises pudo haber cargado con tarjeta o desde su cuenta bancaria sin costo) la transacción total es gratuita. Además, la operación es instantánea.

Si el cliente envia el dinero a través de paypal pero habiendolo cargado desde una cuenta bancaria o tarjeta de crédito específicamente para dicha transacción, el costo de la operanción es 3,4% + 0,30 USD. El emisor decide quien abona este cargo.

Una observación importante es que predeterminadamente las cuentas PayPal son en una moneda principal (en dólares estadounidenses para Argentina) y al recibir un pago en otra moneda (euros, por ejemplo) la conversión de divisa se realiza al tipo de cambio del día con una retención del 2.5%. El tipo de cambio es actualizado 2 veces por día.

Una sólución es abrir cuentas en distintas monedas. En vez de convertir el pago a la divisa principal, se mantiene en nuestra cuenta en la moneda en que se recibió. Cuando necesitamos realizar un pago o transferencia en esta moneda, nos ahorraremos tener que reconvertirla nuevamente (ahorrando un 5% en total). Claro que a la hora de monetizar los fondos se deberán convertir, pero esto se puede hacer en cualquier momento que creamos conveniente.

Paypal aclara que ofrece este servicio (Multiples divisas) para facilitar el comercio electrónico internacional y no debe utilizarse con fines especulativos. Pero los timberos decidirán.

De Paypal a la billetera

GIF - 1.2 KB

Pero, como decía un amigo, la plata no es plata hasta que no sirve para comprar fernet en la despensa.

Como dije más arriba, no se puede asociar una cuenta bancaria argentina una cuenta Paypal (ni para añadir ni para retirar fondos). Esto deja como única alternativa oficial para retirar fondos el envio de un cheque.

Paypal envia un cheque via correo postal certificado por el monto que solicitemos con un costo de u$s 15 fijo, independientemente del monto retirado. El envío para Argentina se realiza a través de Ocasa, y tiene una demora aproximada de 10 días hábiles.

El problema es que este cheque tampoco se puede cobrar en ningún banco, por lo que hay que venderlo en una financiera o agencia de viajes, que cobran una comisión de entre el 2 y el 5%.

Por suerte existe xoom.com. Es un servicio de transferencia de dinero que intenta competir con Western Union, pero a diferencia de este, la operación se realiza únicamente online, el destino puede ser una cuenta bancaria argentina o efectivo en pesos o dólares, y, hete aquí la clave, el origen de los fondos puede ser una cuenta Paypal.

Problema solucionado: nos hacemos una transferencia a nosotros mismos, retirando fondos de Paypal y enviandolos a nuestra cuenta bancaria, o mejor, en dólares que se cobran en cualquier sucursal de Banco Francés.

A diferencia de Wester Union, los cargos de servicio no son porcentuales fijos sino que están tabulados en rangos del monto enviado lo que significa un ahorro considerable en montos grandes. Para cifras montos menores a u$s500, el costo de servicio ronda le 4.5%

Además hay que considerar que al cobrar en pesos, Xoom realiza una conversión de divisa a un tipo de cambio que, al igual que Wester Union, está un par de puntos por debajo de la cotización de mercado. La opción de cobrar en dolares evita esta pérdida, pero tiene un cargo de servicio un 40% mayor, lo que significa un costo de operación real del más de 6%.

Pero hay una forma de salvar esta plata, que convertida a pesos seguramente significarán varios fernés: conseguir un código de descuento. Retailmenot suele tener cupones válidos, ¡de hasta el 100%!

Conclusión: si cobramos desde Paypal (entre cuentas personales) y retiramos los fondos a través de Xoom.com en dólares consiguiendo un cupón del 100%, tendremos toda nuestra platita en el bolsillo, en dólares y sin perder nada en el camino.

¡Espero sirva!

Comentarios (4) | Link

Publicado el 19 de octubre de 2009 | Categoría/s: Linux

Ya somos avispados usuarios de la línea de comandos y hacemos nuestros pinitos administrando un servidor: movemos, bajamos y hasta compilamos directamente en una maquina remota, muchas veces más potente y con más ancho de banda que la nuestra.

Nuestra terminal cliente sólo ejecuta OpenSSH (o Putty en Windows)

Pero cuando se trata de ejecutar un proceso largo y de nula interactividad no tiene mucho sentido seguir conectados ¿Para qué gastar tiempo y recursos (dejar la PC cliente prendida, por ejemplo) si el trabajo sólo se hace en el servidor?

Este caso se da muchas veces, sobre todo (y aquí lo que me interesa) cuando bajamos archivos muy pesados o hacer un mirror de un repositorio completo.

Y aquí cómo resolverlo: usa GNU Screen.

Screen es un multiplexor/virtualizador de terminales, y entre sus muchas e interesantes características incluye el desacople de su proceso padre.

Esto significa que se puede ejecutar una terminal virtual con screen (en una terminal remota por ssh, por ejemplo), ejecutar cualquier proceso en ese entorno y desacoplarlo, pudiendo entonces desloguearse y cerrar la conexión remota dejando el proceso en curso.

Receta paso a paso

  • ejecuta una consola virtual con screen
    1. $ screen
  • Ejecuta tu proceso largo. Por ejemplo, bajar la beta de Ubuntu Karmic Koala en DVD
    1. $ wget http://mirror.mcs.anl.gov/pub/ubuntu-iso/DVDs/ubuntu/9.10/beta/ubuntu-9.10-beta-dvd-i386.iso
  • Desacoplar el proceso con la combinación de teclas Control+A D
  • Desconectarse, tomar unos mates y volver cuando quieras

Para retomar el proceso

  • Conectarnos de nuevo al servidor mediante SSH
  • Listar las consolas virtuales para averiguar el PID
  • Traer a primer plano el proceso en cuestión con

y allí estará el proceso que dejamos corriendo (o al menos los rastros que dejó en su paso).

Y a propósito, los chicos de Tucan Project agregaron soporte para línea de comandos, un buen motivo para usar este truco. ¡A descargar!

Comentarios (0) | Link

Publicado el 30 de septiembre de 2009 | Categoría/s: Linux

Para el Mundial del 2006, compré, como tantos otros que no tenían televisor pero sí computadora, una plaquita sintonizadora de TV: una Kozumi con el chip sintonizador BT878, uno de los más genéricos y bastante bien soportado en linux.

Tuvo poca utilidad en aquel 2006, primero porque argentina no duró demasiado y segundo y principal porque un vecino reclamó potestad sobre la señal del cable coaxil que alimentaba mi chip y mis ilusiones mundialistas.

Quedó cajoneada en algun rincón, hasta que rescaté del olvido la videofilmadora de la familia, una vieja y noble JVC , con un montón de casetitos Compact VHS (que es el formato con el que funciona).

Así que después de mucho patear la tarea, decidí conectar los cables y encontrar la forma de convertir en bytes los recuerdos archivados en esos casettes polvorientos.

Acá mi supercomando mencoder:

  1. mencoder -tv driver=v4l2:device=/dev/video0:input=1:width=480:height=360:norm=ntsc:alsa:adevice=hw.0:amode=1:audiorate=44100:forceaudio:forcechan=1:buffersize=300 -oac mp3lame -lameopts cbr:br=96:mode=3 -af volume=-6:0,channels=1 -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=5000:keyint=125:mbd=2 -vf yadif,crop=464:352:8:2 tv:// -o salida.avi

Son muchos parámetros:

- -tv indica que se va a capturar video, y se le pasan paramétros: driver v4l, un tamaño de 480x360 (aunque después se recorta), preconfigurado para ntsc (29.97 fps).
- Un aspecto importante estos flags son los referidos al audio: se captura el audio alsa, indicando la placa de sonido, el modo y la calidad (mono a 44100hz de ancho de banda)
- El audio se comprime con lame a 96kps constante.
- con -af volume le bajo el volumen 6db, porque de otra manera me salía saturado (estoy capturando desde el microfono). También se fuerza a grabar un solo canal.
- Con -ovc lavc se usa libavcodec (ffmpeg), comprimiendo en mpeg4 a un bitrate de 5000.
- Se aplican 2 filtros de video al vuelo: yadif que es el mejor filtro desentralazador (necesario para captura analógica) y un crop que corta 8 pixeles de los costados, 2 de arriba y 6 de abajo, para evitar la distorción que producen los cabezales con las cintas viejas.

El resultado es un video de unos 250kb/s de calidad más que aceptable.

Por ejemplo, el casamiento de mi hermano Juan, en 1998:

Se me pianta un lagrimón. Cuanta juventud, cuantos recuerdos. ¡Gracias gente!

Comentarios (1) | Link

Publicado el 29 de septiembre de 2009 | Categoría/s: Python

Learning Python de Mark Lutz, ha sido, desde su primera versión en 1999, uno de los libros de cabecera para aprender Python.

Hace unos días salió la 4ta edición, adaptada a las versiones 2.6 y 3.1 de Python y ampliada en varios capítulos.

Lamentablemente, tardará mucho en llegar a la librerías argentinas, pero podés ir leyendo la versión en PDF.

PDF - 7.3 MB
Learning Python 4th Edition
by Mark Lutz, OReilly Oct-2009
Comentarios (1) | Link

Publicado el 20 de septiembre de 2009 | Categoría/s: Python

El problema nº 2 pide obtener la suma de todos los números impares pertenencientes a la sucesión de Fibonacci menores a 4 millones.

El código con el que lo resolví es este:

def fibo(max):
        a, b = 0, 1
        n = a + b
        while n < max:
                yield n
                a, b = b, n
                n = a + b
sum([i for i in fibo(4000000) if i%2 == 0])

El resultado es 4613732.

Explicación

Fibonacci es el "hola mundo matemático" y Python luce su elegancia con este problema.

El aspecto interesante de la función fibo() definida en el código de arriba es que no se trata de una función común sino de un generador. Sintácticamente la diferencia está en que no utiliza la sentencia return sino yield .

La definición de yield. en su acepción de verbo, dice «end resistance, especially under pressure or force;». Ceder, no oponer resistencia.

La diferencia sustancial entre un yield y un return es que el yield devuelve el resultado parcial de cada iteración y hace una "marca de entrada" desde donde se comenzará a ejecutar la próxima vez que la función (el generador) sea invocado.

Esto permite una recursividad con "evaluación perezosa", mucho más eficiente en términos computacionales.

El Filtrado de los numeros impares de la sucesión y la sumatoria es la misma solución que se apliqué en el problema 1.

Comentarios (0) | Link

Publicado el 18 de septiembre de 2009 | Categoría/s: Python

A través del blog de Juanjo Conti descubrí Project Euler, una serie de desafíos matemáticos de enunciación sencilla para resolver con computadoras.

Juanjo estuvo resolviendo los primeros problemas, y yo quise hacer mi intento. El primero plantea obtener la suma de todos los multiplos de 3 o de 5 menores a 1000.

Lo resolví con esta pythonica (lo es?) línea:

sum([i for i in range(1000) if (i % 3 == 0 or i % 5==0)])

El resultado es 233168.

Breve explicación

Se basa en el uso de list comprehensions, una de las "joyas de la corona" de las características de Python.

Es una manera de generar listas de una manera concisa, compuesta por una expresión seguida de uno a más for y una condicionalidad al final

La lista [i for i in range(1000) if (i % 3 == 0 or i % 5==0)] se lee así: crear una lista con todos los elementos (expresión i) en el rango de 0 a 999 (for) cuyo resto de dividirlo por 3 o 5 sea 0 (if).

La función builtin sum() hace la sumatoria de esa lista y... listo. ;-)

Comentarios (1) | Link

Publicado el 9 de septiembre de 2009 |

The principle of successful freelancing, de Miles Burke, es el libro (digital) que estoy leyendo.

This book is intended as a guide to approaching the decision to be your own boss, effecting a smooth transition into a freelance career, and making it a success once you’re there. The book’s holistic approach ensures that it not only covers how to make your freelancing journey a financial success, but also how to do it without risking your health and sanity.

Ser tu propio jefe. No está mal para este mundo donde ese rol tiene connotación negativa.

Quienes quieran chusmear, acá tienen.

PDF - 4.2 MB
The principle of successful freelancing
by Miles Burke
Comentarios (0) | Link

Publicado el 10 de agosto de 2009 |

Administrar muchos sitios SPIP tiene sus bemoles. Yo administro, fácil, unos 30. Cuando hay que actualizar la versión (por cuestiones de funcionalidad, o bien, como la semana pasada, por cuestiones de seguridad), es un trabajo engorroso y aburrido hacer 30 veces lo mismo. Y el trabajo se vuelve exponencial si hay que actualizar los plugins para cada uno

Para evitar eso existe la Mutualización, que desde la versión 2 es realmente muy fácil.

El concepto es simple: un sólo núcleo de SPIP (/ecrire, /prive, /squelettes-dist, /plugins) se comparte para motorizar diferentes sitios, que tendrán los directorios con contenido propio (/squelettes, /config , /IMG, etc), separado del resto

Así, a la hora de actualizar SPIP sólo tenemos que actualizar una sola instalación, tarea que se vuelve trivial si además usamos svn.

Requisito

En general, la mutualización funciona sin muchos pormenores en un servidor LAMP, pero nuestro servidor de hospedaje debe permitir apuntar diferentes dominios a un mismo directorio publico.

Por ejemplo, mi sitio textosypretextos.com.ar apunta a /home/tin/public_html/spip y nqnwebs.com apunta también a /home/tin/public_html/spip.

Es una configuración simple, pero no todos los servicios de hosting lo permiten.

Puesta en marcha

Zip - 39.2 KB
plugin mutualisation

La "mutualización fácil" funciona a través de este plugin, pero que particularmente debe ser instalado en la raiz del sitio y no en la carpeta /plugins

Al descomprimirlo crea una nueva carpeta, /mutualisation, en la raiz de nuestro SPIP mutualizado

Además, incluye un archivo mes_options.php de ejemplo, pero yo te propongo este, que debe ser instalado en /config

  1. <?php
  2.         if (!defined("_ECRIRE_INC_VERSION")) return;
  3.         require _DIR_RACINE.'mutualisation/mutualiser.php';
  4.  
  5.         if (substr($site = $_SERVER['HTTP_HOST'],0,4)!='www.')
  6.                 $site = 'www.' . $site;
  7.        
  8.         define ('_INSTALL_SERVER_DB', 'mysql');
  9.         define ('_INSTALL_HOST_DB', 'server');
  10.         define ('_INSTALL_USER_DB', 'user');  
  11.         define ('_INSTALL_PASS_DB', 'pass');
  12.         define ('_INSTALL_NAME_DB', 'db');
  13.        
  14.         /* Comentario la línea siguiente si utilizará la configuración de prefijos de tabla de más abajo */
  15.        
  16.         //define ('_INSTALL_TABLE_PREFIX', 'granja');
  17.        
  18.         /*
  19.         * Si el nombre del servidor es diferente al DNS ,
  20.         * a veces puede ser problemático y debe ser
  21.         * declarado aquí
  22.         */
  23.         // define ('_INSTALL_HOST_DB_LOCALNAME', 'nom_serveur');
  24.        
  25.         /*
  26.          *      Si el servidor de base de datos no es mysql, debe especificar
  27.          * # define ('_INSTALL_SERVER_DB', 'pg'); // mysql|pg|sqlite2|sqlite3
  28.          *
  29.          * /!\  En PG, es recomendable utilizar la opción creación de usuarios de SQL
  30.          */
  31.        
  32.         /*
  33.          * Crear automáticamente los usuarios SQL (pg|mysql)
  34.          *
  35.          * Esto permite
  36.          * - Tener un usuario root como titular de los derechos de
  37.          * Creación de bases de datos (el usuario con una fase obligatoria de
  38.          * Un nombre es PG - PG no se conecta, sin dar un nombre a BDD)
  39.          * - Para crear los usuarios automáticamente sql
  40.          * Con sólo los derechos de los directores
  41.          * De su base de datos que se creará
  42.          *
  43.          * A continuación, debe sustituir
  44.          *
  45.          * _INSTALL_(USER|PASS)_DB par _INSTALL_(USER|PASS)_DB_ROOT
  46.          *
  47.          * et ajouter dans demarrer_site l'option
  48.          * 'creer_user_base' => true
  49.          */
  50.         # define ('_INSTALL_USER_DB_ROOT', 'mon_root');
  51.         # define ('_INSTALL_PASS_DB_ROOT', '********');
  52.  
  53.         /*
  54.          * Crear las bases de dato via un ping a una URL (metodo AlternC)
  55.          *
  56.          * Il suffit de renseigner l'option url_creer_base, en lui passant les bons parametres :
  57.          * 'url_creer_base' => 'https://bureau.tld/admin/sql_doadd.php?username=USER&password=PASS&dbn='.prefixe_mutualisation($site)
  58.          */
  59.          
  60.          
  61.         /*
  62.          * Transformar en las paginas publicas las URL de imagenes
  63.          * /sites/mon_site/IMG/* -> /IMG/*
  64.          * /sites/mon_site/local/* -> /local/*
  65.          *
  66.          * - Necesita el mod_rewrite (reescritura de url) de apache
  67.          * - Sólo funciona con nombres de dominio mutualización
  68.          * ('http_host' : http://mi_sitio_mutualizado.com)
  69.          * (por lo tanto, no funciona con un subdirectorio - http://mi_sitio_mutualizado.com/misitio/)
  70.          *
  71.          * y añadir en la opción
  72.          * 'url_img_courtes' => true
  73.          *
  74.          * Es posible generar los  .htaccess
  75.          * automaticamente en /IMG y /local
  76.          * gracias a ?var_mode=creer_htaccess_img
  77.          *
  78.          */
  79.        
  80.         /*
  81.          * Indique aqui el nombre del sitio de administración de esta mutualización
  82.          * (o varios, separados por oma)
  83.          * (dpor ejemplo, 'scriibe.net' es el dominio de nivel maximo)
  84.          * para autorizar todos los sitios no definir la constante ;
  85.          * Si el propietario del sitio no se encuentra en los sites/ sino en la razi,
  86.          * escriba '' y agregue 'mutualisation' en $dossier_squelettes
  87.          */
  88.         define ('_SITES_ADMIN_MUTUALISATION', 'nqnwebs.com');
  89.        
  90.         demarrer_site($site,
  91.                 array(
  92.                 'creer_site' => true,        // Creer ou non le site s'il n'existe pas (defaut: false)
  93.                         'creer_base' => false,        // Creer ou non la base de donnee si elle n'existe pas (false)
  94.                         'creer_user_base' => false,  // Creer ou non un utilisateur pour la nouvelle base de donnee (false)
  95.                         'mail' => '',                // Adresse mail pour recevoir un mail lors d'une creation de site mutualise ('')
  96.                         'code' => 'miclave',  // Code d'activation ('ecureuil')
  97.                         'table_prefix' => true,     // Definir automatiquement le prefixe de table (false) ... mettre true si tous les sites dans la meme base
  98.                         'cookie_prefix' => true,     // Definir automatiquement le prefixe de cookie (false)
  99.                         'repertoire' => 'sites',     // Nom du repertoire contenant les sites mutualises ('sites')
  100.                         'url_img_courtes' => true,   // Utiliser la redirection des URL d'images courtes dans la partie publique (false)
  101.                         # 'utiliser_panel' => false, // Utiliser une table externe pour recuperer des identifiants ... (code, user, pass) permettant a un utilisateur d'installer le site (false)
  102.                         'url_creer_base' => ''       // Creer la base de donnees via une URL (methode AlternC)
  103.                 )
  104.         );
  105.        
  106. ?>

Este mes_options.php (retocado por mi) permite que los sitios funcionen con o sin ’www’. También apunta a una única base de datos, donde se encargará de crear las tablas necesarias para cada sitio, diferenciadas por un prefijo.

Sólo resta crear la carpeta /sites en la raiz del sitio, donde irán nuestros diferentes sitios mutualizados.

Al acceder via web a un dominio de un sitio sobre esta mutualización, lo primero que aparecerá es una solicitud de contraseña, definida en array de configuración de mes_options.php (en el ejemplo, la contraseña es miclave)

Luego siguen dos etapas que nos crean la estructura de directorios para este sitio dentro de /sites y las tablas para este sitio en la base de datos compartida. Lo que sigue es el proceso de instalación estándar de SPIP.

¡Listo!

Hay que tener en cuenta que ahora los archivos para nuestro sitio estarán dentro de /sites/dominio/ y es allí donde deberán subirse los esqueletos y demás.

Mutualizar un sitio en producción

¿Qué pasa si el sitio que quiero mutualizar ya está funcionando sobre un spip propio? No problem.

Basta indicar (desde el panel, o solicitando al administrador del hosting) que nuestro dominio debe apuntar ahora a la carpeta donde tenemos el spip mutualizado (en mi ejemplo /home/tin/public_html/spip ), crear el directorio /sites/dominio (donde dominio es la url del sitio que queremos migrar) y mover alli las carpetas /config, /IMG, /squelettes, /local y /tmp (o crear una /tmp nueva) del SPIP en uso al nuevo directorio. [[Estas carpetas, bien podrian ser link simbólicos]. Magia!

Conclusión

Si administrás más de dos sitios spip sobre el mismo servidor, esta configuración te ahorrará trabajo. Avanti: ¡Todos para uno y uno para todos!

Comentarios (0) | Link

Publicado el 10 de junio de 2009 | Categoría/s: SPIP, jQuery

Si Twitter funciona con 140 caracteres los comentarios a nuestros artículos podrían tener 200, ¿no?

Hay una forma fácil de limitar el largo permitido en un campo de texto mediante jQuery, que vaya mostrando de manera interactiva la cantidad de caracteres restantes.

Por ejemplo, esto limita el tamaño de un comentario en SPIP.

<script type="text/javascript">
 $(document).ready(function () {  
     
     $("#texte").before("<div id='chars' style='float:right;font-weigth:strong;margin-right:5px;'></div>");
$(function(){
    $('#texte').keyup(function(){
        limitChars('texte', 200, 'chars');
    })
    });
 });  
 
function limitChars(textid, limit, infodiv) {
     var text = $('#'+textid).val();
     var textlength = text.length;
     if(textlength > limit) {
         $('#' + infodiv).html('No puede ingresar m&aacute;s de '+limit+' caracteres');
         $('#'+textid).val(text.substr(0,limit));
         return false;
     } else {
         $('#' + infodiv).html('Restan '+ (limit - textlength) +' caracteres.');
         return true;
     }
}
</script>

Intrucciones para SPIP

  1. Copiar el código
  2. Pegarlo luego de la baliza #INSERT_HEAD de tu cabecera
  3. (opcional) Cambiarle el límite (el número 200),

¡Listo!

Intrucciones generales

Es igual al anterior, sólo debes asegurarte que tiene en jquery en la página. Luego cambia el selector #texte por el que corresponda al campo que querés limitar.

Ejemplo

Mirá un ejemplo en La Voz de Lanzarote. (click en ’opinar’, en la barra posterior al artículo)

Comentarios (0) | Link

Publicado el 22 de mayo de 2009 | Categoría/s: SPIP, Linux

Como sabemos, el desarrollo de SPIP se realiza a través del sistema de control de versiones Subversion.

A través de Subversion, podemos obtener la ultima version de desarrollo considerada estable

Una de las ventajas de obtener SPIP a través de SVN, es que luego es muy fácil de actualizar.

Subversion asigna un numero de revision a cada cambio realizado al conjunto de archivos. Así, cuando los desarrolladores lo evaluan pertinente, en un determinado momento del desarrollo se empaqueta una nueva version "oficial"

Por ejemplo, la revisión 13982 es la version 2.08 de Spip.

Podemos obtener una revision específica con el parámetro -r. Por ejemplo, el siguiente comando obtendría una copia de SPIP 2.08

Genial, pero para para asegurarnos estar en una revision que se corresponda con una "version oficial" tenemos que saber el número de ID.

En el Trac de Spip se mantiene una tabla donde se especifica esta correspondencia para cada nueva version, pero a decir verdad, es un engorro tener que ingresar sólo para averiguar un número. Mejor hagámoslo automático!

Automatizando la obtención de un SPIP oficial por SVN

  1. #!/bin/bash
  2. #script para una instalacion de spip a traves de svn
  3. if [ $# -lt 1 ]
  4. then
  5. echo "Debe indicar al menos un parametro:"
  6. echo "$0 destino [rev]"
  7. echo
  8. exit 1
  9. fi
  10. if [ $# -eq 2 ]
  11. then
  12. REV=$2
  13. else
  14. echo "Averiguando revision de la ultima release..."
  15. REV=$(svn info svn://trac.rezo.net/spip/archivelist.txt | sed -n '9p' | cut -d' ' -f5)
  16. fi
  17. echo "Recuperando la version $REV de SPIP"
  18. svn checkout -r `echo $REV` svn://trac.rezo.net/spip/branches/spip-2.0/ $1 1>/dev/null
  19. echo "Configurando permisos..."
  20. cd $1
  21. chmod 657 IMG local tmp config
  22. echo "Lanzando el navegador para continuar la instalacion..."
  23. firefox http://localhost/~tin/$1/ecrire

Este script hace el trabajo aburrido por nosotros. Averigua cuál fue la última modificación de archivelist.txt que es un archivo que se modifica en cada nuevo lanzamiento de paquete. ¡Es el dato que nos hacía falta!

Una solución más genuina

Atención: Ya me hicieron caso. Ver actualización

Aunque el hacking (como este) es sano y divertido (y a veces también útil), la solución más genuina sería que los desarrolladores de SPIP mantengan un tag por cada nuevo empaquetamiento y uno que apunte siempre al último.

Por ejemplo, con el siguiente comando deberiamos obtener la version 2.05 (sin saber a qué numero de revision corresponde)

y con este otro obtener la última versión

Esto, por ahora, no está implementado, pero ya hice llegar mi propuesta a l’equipe de SPIP, y lo están discutiendo

Actualización

Gracias a Gilles el Dev Team adoptó mi propuesta y ahora existen Tags en el arbol SVN de spip. En particular,

siempre devolverá la versión estable de la rama 2 de Spip. ¡Bien!

Comentarios (0) | Link

Publicado el 24 de abril de 2009 | Categoría/s: Python

Para suscribirse a la lista de Pyar, una de las tareas (opcional, pero muy bienvenida) es enviar tu "Hola Mundo".

El 17 de enero de 2007 yo me suscribí y mandé el siguiente mensaje.

Estimada gente:

Cumpliendo solemnemente con el paso 2 de las indicaciones de suscripción a la lista, haciendo alarde de mi nerdismo, les dejo mi "hola mundo" (mi primero programa en python!). Se trata de humilde juego via consola que implemento en cada lenguaje en el que intento incursionar. Hete aqui:

Dicha sea la verdad: vengo con muchas ganas de aprender, y por ahora muy poco que aportar (pago solidaridad con sinceridad).

Decidir aprender un nuevo lenguaje es una gran decisión y creo que no me he equivocado con mi elección. Es que son mis primeros pinitos en la programación orientada a objetos, y aunque la facu exige Java (pero no enseña Java), creo que Python es una herramienta mucho mas versatil, accesible y apropiada para el nivel de software que tengo intención/necesidad de desarrollar.

Ahora la parte aburrida. Me llamo Martin, soy de Neuquen y estudio Ingenieria en computacion en Cordoba. Soy programador PHP (uno del montón, que bah) y en particular laburo con un CMS/framework llamado SPIP, que me da de comer y beber. Tengo un weblog, aunque no sobre cuestiones técnicas. www.textosypretextos.com.ar . Y lo más importante: soy hincha de boca.

saludos desde Neuquén a 32ºC. (quien dijo que en el sur hace frio?)

Martín

Mi "Hola Mundo" fue El Número.

Mi primer juego

El Número es un juego de lógica y habilidad mental. Consiste en encontrar el número escondido (generado aleatoriamente) a través de la información

que brinda la máquina en cada intento. El número escondido tiene 4 cifras no repetidas.

- Un digito ’bien’ significa que el hay un acierto en número y posición.

- Un digito ’regular’ significa que el digito existe en el número incógnita, pero no está en la posición correcta.

Por ejemplo si el numero incógnita fuese el 1234 y se arriesga el 2031 el resultado será de dos dígitos regulares (el 2 y el 1) y 1 dígito bien (el 3).

Descarga e instrucciones

Zip - 2 KB
El Número
Martín Gaitán - Enero de 2007

Sobre Linux podés copiar y pegar este listado de comandos en la consola:

Sobre Windows, asegurate tener instalado Python (cualquier versión < 3) y dale hacé doble click sobre elnumero.py

¡Que lo disfrutes!

Comentarios (2) | Link

Publicado el 22 de abril de 2009 | Categoría/s: Empresa

El miércoles 15 de abril de 2009 participé como disertante en las 3º Jornadas Abiertas de Ingeniería en Computación que reune a estudiantes, profesores y profesionales invitados para dar charlas técnicas o de interés para la comunidad de la carrera.

En la anterior edición, diserté sobre Control de Versiones con Subversion. En esta oportunidad pretendí un tema menos técnico pero de interés para un vasto sector de mis compañeros: cómo animarse a dar los primeros pasos profesionalmente sin ser empleado.

La charla se basó en una presentación de Sebastián Desimone, publicada bajo Creative Commons by-nc-ar que escuché en las 7mas Jornadas Regionales de Software Libre, realizadas en Córdoba, en 2007.

Como corresponde ética y legalmente, este trabajo está bajo la misma licencia.

opendocument presentation - 284.8 KB
Ser Freelance: Cómo trabajar en ojotas desde el living de tu casa
Martín Gaitán, abril de 2009

El documento ODP incluye notas y comentarios.

Slidecast

Lamentablemente, la calidad del audio es paupérrima.

Video

Comentarios (1) | Link

Publicado el 19 de abril de 2009 | Categoría/s: Linux

Radiolina es a mi jornada laboral lo que la Spika a la de mi abuelo, en aquellas mañanas de viñas mendocinas.

Es un simple script bash que se vale del mágico mplayer para reproducir las radios más importantes de argentina (y otras mejores que esas).

Para bajar y empezar a disfrutar Radiolina puedes ejecutar los siguientes comandos desde tu consola.

Como frecuentemente lo actualizo, te recomiendo que utilices SVN para bajar el programa. En vez de la primer linea (wget...) utilizar

texte - 3.2 KB
radiolina
script bash
Comentarios (1) | Link

Publicado el 31 de marzo de 2009 | Categoría/s: Linux

Un comando muy práctico para hacer backups de una base de datos MySQL es mysqldump.

Eso hace un backup completo de la base base_de_datos (incluyendo la creación de todas las tablas.

Para restaurar ese backup se hace directamente inyectando el sql al interprete de mysql.

Respaldar sólo algunas tablas de la base

A menudo tenemos multiples sistemas instalados sobre la misma base de datos, Si sólo queremos respaldar algunas tablas bastaría enumerar las tablas luego del nombre de la base de datos

Pero si estas tablas son muchas, es engorroso definirlas una por una. Por suerte, en general, un prefijo asocia todas las tablas de un sistema.

En ese caso, se puede usar el siguiente compando que respalda todas las tablas con un prefijo, En este ejemplo, las que comienzan con "spip_":

¡Que se aproveche!

Comentarios (0) | Link

Publicado el 26 de marzo de 2009 | Categoría/s: SPIP, jQuery

Lorem ipsum es el texto que se usa habitualmente en diseño gráfico en demostraciones de tipografías o de borradores de diseño para probar el diseño visual antes de insertar el texto final.

Cuando estamos desarrollando necesitamos ver cómo quedará el contenido, y debemos recurrir a un copy & paste de caulquier cosa que tengamos a mano.

La ventaja de un Lorem Ipsum sobre otros textos, es que este tiene una distribución del largo de las palabras bastante natural de las palabras lo que en textos largos queda mucho mejor que repetir un mismo fragmento una y otra vez.

Hay muchos generadores de texto Lorem Ipsum en internet, pero lo podemos hacer aún más fácil.

Un Lorem Ipsum automático

Con la ayuda del plugin jQuery Lorem Ipsum de Sander Korve hice un modelo (instalable como plugin) que permite insertar un texto del tamaño que queramos (por omisión, de 4 párrafos).

Podés bajarlo desde acá:

Zip - 32.5 KB
Lorem Ipsum Plugin
version 0.2

O por SVN:

svn checkout svn://zone.spip.org/spip-zone/_plugins_/_test_/loremipsum

Instalación

La instalación es igual que con la de cualquier plugin: descomprimirlo en la carpeta /plugins y activarlo.

Requiere además que los esqueletos tengan la baliza #INSERT_HEAD dentro del header, ya que allí se incluirá el javascript necesario para su funcionamiento.

Funcionamiento básico

La inclusión de un Lorem Ipsum se basa en el modelo lorem.html incluído con el plugin, por lo que hay dos maneras de llamarlo:

- En el cuerpo (texto, descripción, etc) de un artículo: <lorem>

- Predefinido en un esqueleto: #MODELE{lorem}

¡y listo!

Parámetros

El modelo acepta algunos parámetros para configurar la longitud del texto. Por ejemplo <lorem5> creará 5 párrafos.

Pero también se puede especificar más datos:

- type: permite especificar que tipo de resultado se quiere. Las opciones válidas son paragraphs, words o characters para párrafos, palabras o characteres. Así: creará un texto de 25 palabras. El valor por omisión es paragraphs.

- amount: Es lo mismo que el ID pasado al modelo: es lo mismo que . Por ejemplo

[(#MODELE{lorem}{amount=5})]

 [1].

- ptags: Permite agregar las etiquetas <code<>P<>/code> alrededor de cada párrafo. Los valores aceptados son true o false. Por omisión es true.

Una astucia

Una forma de mostrar contenido en un artículo (o cualquier elemento) sin tener que editar cada artículo sólo para poner <lorem> es invocar el modelo siempre y cuando no exista contenido en la baliza

Por ejemplo [2]:

<BOUCLE_article(ARTICLES){id_article}>
<h1 class="#EDIT{titre}">[(#TITRE|supprimer_numero)]</h1>
[<div class="#EDIT{chapo} chapo">(#CHAPO|image_reduire{740,400}|sinon{#MODELE{lorem}{amount=2}})</div>]
[<div class="#EDIT{texte} texte">(#TEXTE|image_reduire{740,400}|sinon{#MODELE{lorem}{amount=5}})</div>]
</BOUCLE_article>
Comentarios (0) | Link

Publicado el 21 de marzo de 2009 | Categoría/s: Linux

Efecto Tábano es el programa radial de mi amigo Fernando Barraza. Objetivamente, uno de los mejores programas radiales de Argentina.

Lamentablemente, desde que me vine a Córdoba tuve que conformarme con los fragmentos de entrevistas o especiales que Fernando subía a la web. Pero ahora que la Radio Calf-UNC está online, la alegría está completa.

El único problema que queda es que no todos los días tengo el tiempo de escucharlo de 16 a 18hs, Necesitaba grabarlo para escucharlo offline.

Bien podría haber hecho esto localmente pero como al sitio lo administro yo, dije... ¿por qué no grabar el programa directamente desde el servidor, y que cualquiera pueda bajarlo cuando quiera?

Aquí está mi podcaster automático para Efecto Tábano.

La idea

Todo se basa en el glorioso Mplayer, Mplayer es capaz de reproducir casi cualquier formato en streaming.

Por supuesto, no habrá sonido en esa "reproducción" sobre el servidor, pero lo que queremos es la info para grabarla.

En vez de enviarla a la placa de sonidos, la información cruda (el sonido WAV) lo enviamos a un archivo fifo desde donde lame obtendrá su fuente de datos para comprimir a MP3 on the fly.

Todo esto, claro, se ejecutará al horario del programa (y durante el tiempo que se indique, en este caso casi 2 horas) mediante una tarea cron

Instalando lo necesario

Como anticipé, hace falta mplayer y lame. Estos programas en general no se encuentran en el servidor (por ejemplo Dreamhost) así que hay que instalarlos. Como tampoco somos root (la gran mayoría de las veces) habrá que compilarlos desde las fuentes e instalarlos a nivel usuario.

primero crear, si no existiése, un directorio /bin donde irán nuestros programas.

mkdir bin
chmod 775 bin

Mplayer y mencoder

wget http://www3.mplayerhq.hu/MPlayer/releases/codecs/essential-20061022.tar.bz2
bunzip2 essential-20061022.tar.bz2
tar -xf essential-20061022.tar
mv essential-20061022 $HOME/lib
wget http://www3.mplayerhq.hu/MPlayer/releases/MPlayer-1.0rc1.tar.bz2
bunzip2 MPlayer-1.0rc1.tar.bz2
tar -xf MPlayer-1.0rc1.tar
cd MPlayer-1.0rc1
./configure --prefix=$HOME --codecsdir=$HOME/lib/essential-20061022
make
make install

LAME

wget http://nchc.dl.sourceforge.net/sourceforge/lame/lame-3.97.tar.gz
tar -zxvf lame-3.97.tar.gz
cd lame-3.97
./configure "--prefix=$HOME" "--enable-shared"
make
make install

Con eso ya tendríamos los programas necesarios en ./bin

El script podcaster-efectotabano.sh

#!/bin/sh
#
# recorder &#8212; wrapper to pull remote audio stream and convert contents
# to mp3

# Path and arguments to lame (mp3 encoder)
lame="$HOME/bin/lame -S -b 32 -m m"

# Path and arguments to mplayer (stream decoder)
mplayer="$HOME/bin/mplayer -quiet"

# Where to put the output files
odir="$HOME/efectotabano.com.ar/podcast"

showname="efectotabano-`date +%Y-%m-%d`"
duration="6660"
url="http://78.159.108.83:8690/"

fifo="${showname}_fifo"
ofile="$odir/${showname}.mp3"

#- end config ----------------------------------------------------

mkfifo $fifo
$lame $fifo $ofile &
$mplayer  -vc null -vo null -ao pcm:file=$fifo $url &

sleep 5
pids=`ps auxww | grep $fifo | awk '{print $duration}'`

sleep `echo ${duration} | bc`

kill $pids
rm $fifo

La primera parte permite configurar las rutas y parámetros de los programas a usar, así como el formato y destino del mp3 de salida.

En este caso los parámetros de lame indican que se grabará a 32kbps en mono.

Los mp3 de salida irán a este destino

Este script se ejecuta de lunes a viernes a las 12:09 hora del servidor (16:09 en argentina) y durante 6660 segundo, de modo que termina tentativamente junto con la finalización del programa.

Para configurar la tarea en cron ejecutar crontab -e. La tarea a agregar luce así:

09 12 * * 1-5 ~/bin/podcaster-efectotabano.sh

Eso es todo. Todos los días, de lunes a viernes tendré mi programa para descargar.

TO DO

Por supuesto, para que esto sea un podcast le falta la sindicación. Por lo tanto, habría que agregar la tarea de injectar información pertinente en una base de datos del cual generar el XML de sindicación.

Lo dejo para una segunda etapa. Me tengo que ir a escuchar o melhor programa do mundo.

Comentarios (1) | Link

Publicado el 15 de marzo de 2009 | Categoría/s: SPIP

Hace algunos días, en spip-es se planteó la duda de cómo controlar una cabecera diferente para algunas secciones en particular.

Xabi aportó la solución canónica, que es crear esqueletos ad-hoc para cada sección difente, valiendose de los esqueletos con forma rubrique-X.html (donde X es el ID de la sección).

Esto se describe en el apartado "Para ir más lejos" de la documentación.

En este caso particular, sólo se quería mostrar el logo en la cabecera para algunas secciones. El problema es que las secciones "diferentes" serían iguales entre sí, pero invocando distintos esqueletos. Esto contradice el principio DRY siempre deseable en todo desarrollo de software.

Una forma sencilla, pero a la vez parcial de resolver esto, es hacer un enlace duro entre los esqueletos que son iguales.

Por ejemplo, la sección 2, la 4 y la 6, tendrán el mismo esqueleto. Entonces creamos el rubrique-2.html y definimos rubrique-4.html y rubrique-6.html como enlaces duros al primero. Desde la línea de comandos:

$ ln rubrique-2.html rubrique-4.html
$ ln rubrique-2.html rubrique-6.html

Esta solución funciona, pero es sólo para servidores *nix y teniendo acceso a la consola (por SSH, por ejemplo). Además, hay que documentar bien qué se está haciendo, porque da lugar a errores cuando dos esqueletos "linkeados" intentan ser iguales.

Por suerte, hay varias otras maneras de resolver esto,

Filtros de condición o filtro match

Esta solución, es la que aportó Juan Pablo Portugau.

Lo que plantea, es usar la baliza #ID_RUBRIQUE (que obviamente, devuelve el número de la sección) con filtros de comparación. Es, hablando en geek, un simple if: Si es la sección 2, mostrar el logo. Sino, nada:

En código SPIP:

[(#ID_RUBRIQUE|=={2}|?{'#LOGO_RUBRIQUE',''})]

La limitación de esta solución se da cuando son múltiples los valores posibles. En nuestro caso, se debe mostrar el logo cuando se trata de la sección 2, de la 4 o de la 6. Juan Pablo propone anidar esta estructura.

[(#ID_RUBRIQUE|=={2}|?{'#LOGO_RUBRIQUE',[(#ID_RUBRIQUE|=={4}|?{'#LOGO_RUBRIQUE',[(#ID_RUBRIQUE|=={6}|?{'#LOGO_RUBRIQUE',''})]})]})]

Aunque es sintácticamente correcto, el código resultante es bastante inmantenible para un ser humano con cerebro normal y el monito parseador de SPIP queda agitado.

Para eso existe el filtro match, que se vale de las expresiones regulares para que hagamos nuestro festín.

Lo de arriba, puede reducirse a esto:

[(#ID_RUBRIQUE|match{^(2|4|6)$}|?{'#LOGO_RUBRIQUE',''})]

El filtro devuelve VERDADERO si el valor de #ID_RUBRIQUE empieza con 2, 4 o 6 y termina con nada. Que es, dicho de otra manera, lo que queremos.

Y aún más claro: bucles como filtros

Las expresiones regulares no son moco de pavo, diría mi abuela. Super potentes, pero poco escalables en la curva complejidad-comprensibilidad.

Hay una solución que es muy útil, sencilla pero no trivial: usar un bucle como filtro.

<BOUCLE_muestra_logo(RUBRIQUES){id_rubrique IN (1,2,4)}{id_rubrique}>
    #LOGO_RUBRIQUE
</BOUCLE_muestra_logo>

La explicación es de la lógica de conjuntos: los criterios de un bucle funcionan como condiciones AND. Deben cumplirse todas. En este caso, el primer criterio {id_rubrique IN (1,2,4)} exige que el id_rubrique sea 1, 2 o 4. En el segundo {id_rubrique}, se exige que sea el que viene en contexto. Por lo tanto, este bucle sólo funcionará (mostrará el logo) si el id_rubrique del contexto es 1, 2 o 4. En lógica, es una operación O exclusiva

Funciona, es más legible que cualquiera de las otras soluciones y además permite una clausula ELSE mucho más accesible, simplemente usando la estructura completa del bucle.

<BOUCLE_muestra_logo(RUBRIQUES){id_rubrique IN (1,2,4)}{id_rubrique}>
    #LOGO_RUBRIQUE
</BOUCLE_muestra_logo>
</B_muestra_logo>
   [código si no es 1, 2 o 4]
</B_muestra_logo>

Como siempre, espero sirva mi aporte.

Comentarios (0) | Link

Publicado el 12 de marzo de 2009 | Categoría/s: SPIP, jQuery

Muchas balizas SPIP generan código HTML como salida (las balizas #LOGO_* y los filtros |image_* son los más notorios) y frecuentemente necesitamos o queremos modificar este código autogenerado en nuestros esqueletos. Hay diversos filtros para ayudarnos a esto (inserer_attribut para insertar atributos y extraire_attribut para extraer el valor de uno generado) pero son particularmente largos y tediosos de tipear.

Más allá de eso, aunque uso estos filtros bastantes seguido para implementar cosas como galerías de imágenes, todavía pienso lo difícil que es escribir las palabras en francés sin equivocarme. Por suerte, un pequeño wrapper, puede suavizar este inconveniente.

Cuando se trata de acceder y modificar atributos de valores de atributos nada, en mi opinión, llega tan lejos como la API de atributos de jQuery. El método de jQuery attr por sí solo, permite leer y escribir el valor de cualquier atributo en cualquier nodo. Recibe uno o dos parámetros, el nombre del atributo, y opcionalmente, el valor.

Si sólo se especifica el nombre, entonces attr extrae y devuelve el valor de ese atributo. Si ambos parámetros son pasados al método, entonces attr modifica el objeto configurando el atributo en cuestión con el valor dado. Es jerga de Programación Orientada a Objetos, es un estilo de interfaz "polimórfica" — cuando un solo método tiene dos comportamientos complementarios que son distinguidos por el número y/o el tipo de los argumentos dados — que está por todos lados en jQuery y es una de las razones por las que este framework es tan conciso y productivo.

Considerandola como la mejor estructura para este tipo de interfaces que conozco (y también, que uso diariamente), decidí ue mi wrapper tendría que copiarlo. Así fue como el attr nació.

Como el método de jQuery, el filtro attr de SPIP toma uno o dos parámetros (y un objeto "implícito", pero lo ignoraremos por el momento). Si sólo pasamos uno, este lo remite como entrada a extraire_attribut para obtener el valor correspondiente. Si se lo llama con dos parámetros, entonces llama a inserer_attribut para modificar el objeto.

Como la idea, el código es razonablemente sencillo; la únca

Like the idea, the code is reasonably straightforward; quizas lo único un poco inusual el uso de func_get_args para obtener el conjunto de los argumentos pasados a la función llamada. Con ese array podermos usar count para saber cuantos argumentos se pasaron y decidir qué se debe hacer. Esto es más seguro que especificar y evaluar valores por defecto (FALSE o NULL, por ejemplo) porque algunos usuarios genuinamente podrían querer usar esos valores (supongamos que NULL signifique eliminar el atributo en una futura versión).

include_spip("inc/filtres");
 
/**
 * The `attr` function allows the user to get and set the attributes of an HTML tag.
 * It is intended to be used as a SPIP filter and depends on existing SPIP functionality.
 *
 * @param $tag
 *     The HTML code.
 * @param $name
 *     The name of the attribute.
 * @param $val...
 *     The new value for the attribute $nom. Optional.
 * @return
 *     If $val was given, the code for tag with $name=$val
 *     Otherwise, the value for the $name attribute in $tag.
 */

function attr($tag, $name){
        $args = func_get_args();
 
        if (count($args) > 2) {
                // SET
                return  inserer_attribut($tag, $name, $args[2]);
        } else {
                // GET
                return extraire_attribut($tag, $name);
        }
}

Simplemente copia el código en mes_fonctions.php (Mira "Agregar funciones propias" en la documentación sobre filtros de spip) y luego usa el filtro attr en tus esqueletos:

<a href="[(#FICHIER|attr{src})]" class="lightbox" title="#TITRE">
    [(#FICHIER|image_reduire{100,100}|attr{alt,#TITRE})]
</a>

Hay algunos cambios que se puede hacer a esta función: pasar $args directamente a inserer_attribut y extraire_attribut en vez de las variables individuales, agregar un parámetro $value=FALSE que sólo sirva para la claridad de la documentación , y el mencionado, eliminar atributos cuando se pase por ejemplo NULL como parámetro.

Una nota final: probablemente necesites correr PHP 5 para que esto funciones — la docu de func_get_args menciona la versión 5.3.0 — y el código de arriba fue modificado luego del último testeo, pero debería funcionar de cualquier manera.

Comentarios (0) | Link

Publicado el 10 de marzo de 2009 | Categoría/s: SPIP

Desde la versión 1.4, SPIP tiene una baliza calculada #INTRODUCTION que como su nombre indica, sirve para presentar una introducción al artículo completo.

En la documentación explica

#INTRODUCTION: [SPIP 1.4] si el artículo contiene una descripción, esta se utiliza aquí; si no, SPIP muestra los 600 primeros caracteres del inicio del artículo (del epígrafe, y luego del texto).

En la versión 1.92 se incorporó otro atajo para indicar el largo del texto mostrado (sobrecargando los 600 caracteres por omisión).

Así, #INTRODUCTION{150} mostrará la descripción, si existe, o los primeros 150 caracteres del epigrafe y/o el texto.

Pero con la versión 2 llegó por fin un control más profundo para los redactores. Es posible definir cual es el texto que se mostrará con #INTRODUCTION encerrandolo entre la etiquetas <intro>...</intro> en el cuerpo del artículo. [1]

Así podemos redactar nuestro artículo con la siguiente estructura:

Suponiendo que la baliza #INTRODUCTION se muestra en el esqueleto de seccion, allí se vería el texto

Esta oración es la introducción al articulo.

Y donde esté la baliza #TEXTE:

Esta oración es la introducción al articulo. Y acá sigue mi artículo completo.

¡Espero sirva!

Comentarios (3) | Link

Publicado el 9 de marzo de 2009 | Categoría/s: Python

Python es un lenguaje de programación interpretado, interactivo y multiplataforma, que con su facilidad y potencia hace las delicias de miles de programadores (y sin saberlo, también de los usuarios de los programas que estos desarrollan) alrededor del mundo.

La comunidad de Python Argentina es particularmente activa, solidaria y muy capaz técnicamente.

Esta charla fue dada por Facundo Batista, uno de los fundadores de PyAr, en las 7mas Jornada Regionales de Software Libre realizadas en Córdoba, Argentina, en 2007.

Aquí la presentación

Si te interesa saber un poco más, instala Python en tu computadora (en caso de que no esté ya instalado, claro) y lee el tutorial. Luego podés ver las recomendaciones de la comunidad para saber como seguir. Y por supuesto, ¡inscribite en la lista de correo!

Comentarios (0) | Link

Publicado el 7 de marzo de 2009 | Categoría/s: SPIP

Más por costumbre que utilidad solemos poner la antigüedad de un sitio web al pie de página, asociado al símbolo ©, o (cc) si usamos Creative Commons.

En el 2007 hicimos el sitio, y en este 2009 todavía muestra.

© 2007

¡Muy feo! Aunque no hayamos actualizado el sitio desde entonces, nuestro deber, como buenos mentirosos, es lograr que el visitante no se entere.

Así que podemos hacer que el año, o el período Año inicio - Año actual se actualice automáticamente.

Muy simple:

  1. &copy;
  2. <BOUCLE_yearbegin(ARTICLES){par date}{0,1}>
  3.    #SET{year, #DATE|annee} #GET{year}
  4. </BOUCLE_yearbegin>
  5. [(#GET{year}|=={#DATE|annee}|?{'' , - #DATE|annee} )]

Explicación

- Por convención, asumimos que el año de inicio del sitio es el año del primer artículo publicado, lo cual a mi me suena bastante lógico.
- Un bucle recupera esta información, la muestra y a la vez la guarda en una variable spip

#SET{year, #DATE|annee}

.
- Fuera del bucle comparamos el año ya mostrado con el actual, obtenida de la baliza #DATE sin contexto. Si son iguales, no se muestra nada más (para que no quede algo como © 2009 - 2009, que quedaría bien feo). Pero si son distintos, se muestra el año actual

El resultado, será

© 2007 - 2009

Y si la lógica o el reloj del servidor no fallan, en cada año nuevo se incrementará el año final del período sin que toquemos una línea de código.

Comentarios (0) | Link

Publicado el 27 de febrero de 2009 | Categoría/s: SPIP

Con SPIP 2.0, más precisamente en la revisión 13407 se agregaron algunos esqueletos al juego de esqueletos estándar.

Unos muy interesantes son los que permiten suscribirse a los comentarios.

squelettes-dist/rss_forum_article.html
squelettes-dist/rss_forum_breve.html
squelettes-dist/rss_forum_rubrique.html
squelettes-dist/rss_forum_syndic.html
squelettes-dist/rss_forum_thread.html

Por ejemplo, en el foro de un articulo, podriamos incluir el siguiente código, antes del bucle de comentarios de un artículo:

<a title="Sindicar los comentarios de este artículo" rel="alternate" href="[(#URL_PAGE{rss_forum_article}|parametre_url{id_article,#ID_ARTICLE})]">[<img width="16" height="16" alt="Seguir la vida del sitio" src="(#CHEMIN{feed.png})"/>] Suscribite a los comentarios de este artículo </a>

Un código análogo, llamando al esqueleto correspondiente y pasando el parámetro correcto, sirve para las breves, las secciones, los artículos sindicados y los hilos de discusión (en foros con comentarios anidados).

Lamentablemente, el RSS aun no es de uso masivo, pero es una buen incentivo ofrecerlo a quien lo desee.

Comentarios (5) | Link

Publicado el 26 de febrero de 2009 | Categoría/s: SPIP, jQuery

Uno pequeño truco con jQuery para mostrar u ocultar un bloque de información. Basado en una respuesta que dí en la lista Spip-es.

Comentarios (0) | Link

Publicado el 23 de febrero de 2009 | Categoría/s: SPIP, Web 2.0

Un screencast y algunos ejemplos de esta potente herramienta para manipular fuentes de información

Comentarios (3) | Link

Publicado el 23 de febrero de 2009 | Categoría/s: SPIP

Un juego de esqueletos con énfasis en la usabilidad y la accesibilidad

Comentarios (0) | Link

Publicado el 21 de febrero de 2009 | Categoría/s: SPIP, Desarrollo web

El trabajo de un desarrollador web cuesta mechones de cabello a la hora de enfrentar al inmundo, malnacido e infeliz Internet Explorer 6. Horas y nervios perdemos intentando que nuestros sitios se vean decentemente en este navegador, que pese a tener casi 8 años de anitgüedad, aun tiene cuota de mercado. ¡Es hora de decir basta! Tomemos las armas y declaremosle la guerra a Internet explorer.

¿Cuáles son nuestras armas?

Te propongo dos, faciles y potentes:

- El script modificado por mí de la campaña End 6!. Sólo debes copiar este código y pegarlo en el header de cada página de tu sitio, o sea entre <head> y </head>.

Si un visitante llega usando el vetusto y abominable navegador, verá un cartelito como este:

- El plugin para spip Cambia el navegador! que al instalarlo y activarlo, muestra un mensaje en la cabecera de todo el sitio público si el visitante usa IE6 (o más viejo!)

Zip - 89.4 KB
Cambia el Navegador!

Puedes bajar este plugin (multilingüe) desde aquí.

Basta de ’caldo gordo’

Como desarrolladores, tenemos cosas mejores que hacer que continuar garantizando la compatibilidad con lo arcaico, perdiendo el tiempo en torno a errores ajenos a nuestros desarrollos. Todo el tiempo dispensado allí debería ser concentrada en conquistar los nuevos horizontes que requieren nuestra atención como, por ejemplo, la web móvil.

Y en gran parte, esta situación es nuestra responsabilidad. Todos los que trabajamos en internet (y los que la usamos con pasión) conocemos y odiamos con fundamentos el Internet Explorer 6. Pero justamente nosotros, por tener razones, somos responsables de difundirlas tanto como podamos para educar tecnológicamente a los usuarios más inexperimentados.

¡A ganar la batalla final!

Comentarios (2) | Link

Publicado el 14 de febrero de 2009 | Categoría/s: Software, SPIP

Una presentación que hice con mi amigo Pablo Martínez sobre Control de Versiones con Subversion

Comentarios (1) | Link

Publicado el 12 de febrero de 2009 | Categoría/s: SPIP

Con un poco de coca-cola en la sangre, retomé esta madrugada un proyectito que tenía: adjuntar fotos de un album de Picasa a un artículo.

Comentarios (0) | Link

Publicado el 18 de marzo de 2008 |

jQuery es la más elegante librería javascript de las muchas que circulan por la red. Aquí una breve introducción a sus características y potencialidades

Comentarios (1) | Link

Publicado el 12 de febrero de 2005 | Categoría/s: SPIP

Los esqueletos de http://www.aten.org.ar disponibles para la descarga

Comentarios (0) | Link

Publicado el 2 de septiembre de 2004 | Categoría/s: SPIP

SPIP (Sistema de Publicación para una Internet Participativa, de sus siglas en francés) es un software libre (GPL) en PHP y MySql con la estructura ideal para desarrollar sitios tipo revista en línea, pero también potencia y sencillez sufiente para lograr cualquier objetivo. Spip se comoporta como un espacio donde un grupo de colaboradores escribe textos de contenido y los/as lectores/as pueden comentarlos.

Spip es más un espacio activista, permite la generación de debates con su propio sistema de foros asociados a artículos secciones y noticias breves. Como ya hay cientos de este tipo de software muy buenos.. ¿por que es mejor SPIP?.

Comentarios (0) | Link



NqN/webs :: Desarrollo, Diseño y Hosting de Sitios Web por Martín Gaitán
Neuquén & Córdoba - Argentina - © Año 2004/2009 - Tel (+54) 0351 460·1524 - Celular: (+54) 351 153·308454
Contacto | Pagos | RSS | SPIP | Usa Firefox