PostgreSQL10 Slonik

Liberado PostgreSQL10: importantes novedades

PostgreSQL10 incluye una gran cantidad de mejoras y novedades, como replicación lógica nativa, particionado de tablas declarativo y un paralelismo de consulta mejorada. Otro aspecto a tener en cuenta es el cambio de formato en la versiones, utilizando números con decimales para las versiones menores (por ejemplo, 10.1) y unidades enteras para las mayores (por ejemplo, 11).

 PostgreSQL10

PostgreSQL10 Slonik
PostgreSQL10 Slonik

Aspectos más destacados de PostgreSQL10 en su lanzamiento (esta es una traducción al castellano de la página oficial en idioma inglés): Continue reading

free as in freedom

Feliz Día del Software Libre 2017

De antemano os decimos que libre no quiere decir necesariamente que es gratis: una cosa es compartir y enseñar y otra muy distinta es que trabajemos gratis. Manejamos el Software Libre (así, con mayúsculas, porque es un ente) desde el punto de vista del servicio, de horas trabajadas, de que podemos automatizar las tareas, sí pero que la instalación, monitorización y mantenimiento (en ese orden) ocasiona “horas hombre” u “horas mujer” de trabajo duro y que conlleva una gran responsabilidad, éso es por lo que cobramos. Ahora bien, allá aquellos que piensan que trabajamos encerrados en “neveras” con nuestros ordenadores y que nos las pasamos “tuiteando”, bueno tratamos siempre de convencer, que es más importante que vencer; tercer sábado de septiembre ¡FELIZ DÍA DEL SOFTWARE LIBRE!

free as in freedom
free as in freedom

Continue reading

Chromium Web Browser Logo

Chromium extension tutorial

Por supuesto que no estamos hablando del elemento químico cromo (“chromium” en inglés) sino del popular navegador web de código abierto para todos. Lo que desarrollaremos es una “extensión”, una herramienta integrada al navegador y que tiene muy diferentes propósitos. Con fines didácticos haremos una extensión muy sencilla que nos redirige hacia una página web que nos devuelve simplemente nuestra propia dirección IPv4, ¡manos al teclado!

¿Qué es una extensión para Chromium?

Chromium Web Browser Logo

Como ya lo definimos al principio, una herramienta puede tener fines diversos, uno o más:

  • Pueden ser usadas para notificarnos si tenemos nuevos mensajes de correo electrónico por medio del pequeño icono que se coloca al lado de la barra de direcciones.
  • Si no hemos iniciado sesión en nuestra cuenta de correo-e basado en web, podemos hacer click en el icono para ir a la página donde introduciremos nuestras credenciales (¡Cuidado con las páginas falsas o “phishing”!).
  • Podría alertarnos si una palabra clave en particular aparece en la página que estemos visitando.
  • Podríamos programarla para NO cargar las imágenes de un sitio determinado -o todos los que visitemos-.
  • Tal vez sería útil para alertarnos de la modificación de una página (aunque para ellos hay lectores RSS específicos para ese trabajo) o su cambio de estado.
  • ¡Incluso, si somos aventureros, nos permitiría programar una calculadora!

Como ven los usos son muchos y variados, nuestra imaginación no tiene límites más sin embargo el entorno donde va a funcionar nuestra novel extensión sí que está supeditada al navegador Chromium. Esencialmente una extensión es una pequeñita página web que está alojada en un navegador web – en este caso Chromium – y que además puede acceder a ciertas funciones API (“Application Programming Interface“: conjunto de clases, métodos y funciones normalizadas).

La que nosotros vamos a realizar es bastante modesta y a medida que avanzemos la iremos profundizando más, pero la idea es introduciros en esta área de programación en un entorno de desarrollo bastante peculiar.

Creando el proyecto.

Pues que para comenzar crearemos en nuestro disco duro, donde gustemos, una carpeta con el nombre “KS7000_ConoceTuIPv4” – o el nombre que vosotros querais, sed de libre albedrío, lo importante es que aprendamos los conceptos y procedimientos-.

Primer componente de nuestra extensión en Chromium.

Como somos inclinados al dibujo técnico más que al dibujo artístico (¡Ea, que por allí viene nuestro tutorial sobre Inkscape!) lo que hicimos fue redimensionar un logotipo en formato PNG (que ya teníamos rodando por internet) a un tamaño de 16 por 16 píxeles ya que necesitados una pequeña interfaz gráfica para el botón donde nuestros usuarios harán click y abrirán nuestro trabajo. Cuando “subamos” – y especifiquemos- este icono a Chromium no tendremos que programar línea alguna: ya el navegador sabrá qué hacer al evento de hacer click sobre nuestra pequeña obra de arte microscópica (935 bytes “pesa” el fichero):

KS7000_ConoceTuIPv4 (icono)

Precisamente queremos hacer hincapié en este punto: esa imagen pequeñita que vamos a especificar ya Chromium le añade el evento click para cargar y ejecutar los siguientes componentes que vamos a crear, eso es, en sí, una Interfaz de Programación de Aplicaciones “API” -normalizadas en un ambiente determinado (Chromium, en este caso) -.

Creando un archivo de manifiesto.

Un manifiesto es simplemente una declaración de propósitos o programas. Para este caso es un fichero llamado manifest.json y por su extensión deducireis que está en lenguaje JSON: JavaScript Object Notation, el cual permite el intercambio de información entre cliente y servidor. Aunque está basado en la norma ECMA-262 3ª edición de 1999 nosotros consideramos que es una norma de facto. En todo caso no representa mayor misterio, tal como lo es XML, el JSON (a menos que guarde datos binarios) es plenamente legible tanto a humanos como a máquinas, pasemos a analizar su estructura mínima necesaria:

{
  "manifest_version": 2,
  "name": "KS7000_ConoceTuIPv4",
  "version": "1.0",
}

Explicado línea por línea, los tres primeros elementos son obligatorios:

  1. “manifest_version”: toma el valor 2 -sin comillas- para indicar que es a partir de la versión 18 de Chromium que funcionará la extensión. Al momento de escribir este reportaje vamos por la versión 59 así que ya sabeis que la versión 1 está obsoleta e inútil, de hecho. Notad cada coma para indicar separación de componentes, lo colocamos antes del fin de línea y retorno de carro.
  2. “name”: con hasta un máximo de 45 caracteres, es como identificaremos nuestra extensión y tratad que sea bien original y único si es que quereis algún día hacerlo famoso por internet y evitar malentendidos con otros programadores o incluso poderosas corporaciones.
  3. “version”: pues la numeración que utilizemos para identificar los cambios que le hagamos, y aunque está entrecomillado no os equivoquéis: son cuatro enteros de ntreo cero y 65535 separados por puntos y sirven para identificar – y actualizar a nuestros usuarios si hacemos una mejora -. En nuestro ejemplo colocamos “1.0” ¿Dónde diablos están los otros dos números faltantes? Pues en realidad nuestra versión es “1.0.0.0”, tened mucho cuidado al numerar porque como dijimos se usa para comparar y actualizar, de ser necesario, a nuestros usuarios.

Más adelante ahondaremos en otras propiedades que deberíamos agregar y que implican otros ficheros en nuestra mini aplicación, per antes de finalizar esta sección os contamos que hay otras propiedades interesantes:

  • “description”: la descripción de lo que realiza nuestra extensión, para lo que sirve, sed breve y conciso; entrecomillad.
  • “short_name“: que soporta hasta 12 caracteres y es especialmente útil para titular las pestañas y el lanzador de aplicaciones (en teoría).
  • “version_name”: un nombre no necesariamente numérica, si queremos colocarle un nombre afectuoso, deberiamos tratar de que sea único.

Así las cosas nuestro archivo de manifiesto va quedando como sigue:

{
  "manifest_version": 2,
  "name": "KS7000_ConoceTuIPv4",
  "short_name": "KS7000_IP",
  "description": "Esta extensión os permitirá saber vuestra dirección IPv4.",
  "version": "1.0",
  "version_name": "TuIPv4",
}

¿Acciones de página o acciones de navegador?

Aunque dijimos que Chromium sabría qué hacer con nuestra extensión, esto no es totalmente cierto ya que en esta API desarrollaron dos aciones principales de la cual debemos especificar que nuestra extensión realize alguna de las dos (o ninguna: si es ninguna pues no obtenemos ningún resultado, es una extensión inútil).

  • Acción de navegador: se ejecutará en cualquier pestaña y paǵina que abramos y permite que nuestros usuarios interactuen con nuestra extensión (ejecutar una orden o cambiar las preferencias, por ejemplo).
  • Acción de página: es un icono que indica un estado o condición a la página que estamos visitando (¿recuerdan que propusimos, al principio, una extensión que buesque y notifique la existencia de una palabra clave? pues eso, se puede activar -o no- si esa palabra clave está presente). Esta acción NO permite interactuar con los usuarios, es más bien informativa.

Nosotros usaremos la acción de navegador para lo cual debemos escribir:

"browser_action": {}

y colocamos entre los corchetes los elementos que queremos especificar y que a continuación especificamos:

 "default_icon": "KS7000_ConoceTuIPv4.png",
 "default_popup": "aviso.html"

La primera línea indicamos que utilice el ícono que os mostramos al principo, pero !ah,caramba! ¿habiais dicho que Chromium sabrá que hacer por nosotros? pues aquí el detalle no es culpa de Chromium ya que debido a los múltiples dispositivos (hardware) que pueden ejecutar este navegador web son muy diversos, los tamaños de pantalla son muy diversos también así que debemos -en teoría- hacer íconos de diferentes tamaños Y CHROMIUM SE ENCARGARÁ DE MOSTRAR EL QUE SEA DEL TAMAÑO ADECUADO AL DISPOSITIVO y tal como prometimos nos “harán” el trabajo a nosotros los programadores.

Acá nos quedaremos con un solo ícono, queda para vosotros estudies cómo especificar más iconos. La segunda línea establece cuál archivo .html queremos mostrar cuando el usuario haga click, y de nuevo es cuestión de tener variedad de opciones ya que podemos hacer varios ficheros .html (según la complejidad de nuestra extensión) pero debemos decirle al navegador cual queremos que muestre primero, así solo sea una la que “subamos” ¡NO ESTAMOS PROGRAMANDO EN PYTHON, TAMPOCO ESPERÉIS MILAGROS!

Archivo de manifiesto, versión final, debidamente indentado.

{
  "manifest_version": 2,
  "name": "KS7000_ConoceTuIPv4",
  "short_name": "KS7000_IP",
  "description": "Esta extensión os permitirá saber vuestra dirección IPv4.",
  "version": "1.0",
  "version_name": "TuIPv4",

  "browser_action": {
    "default_icon": "KS7000_ConoceTuIPv4.png",
    "default_popup": "aviso.html"
  } 
}

Elemento emergente de interfaz.

Ya sabemos que nos falta ahora un elemento, el “default_popup” al cual le asignamos el nombre “aviso.html” y como este tema no es un tutorial de HTML5 pues de una os colocamos el código del fichero de marras:

<!doctype html system "about:legacy-compat">
<html lang="es-419">
  <head>
    <meta charset="UTF-8">
    <title>KS7000</title>
  </head>
  <body>
    <h1>KS7000_ConoceTuIPv4</h1>
    <a href="http://www.soporteweb.com/" target="_blank">Haz click para saber saber vuestra dirección IPv4</a>
  </body>
</html>

“Subiendo” nuestra extensión.

Pues tanto como “subir” no será, no vamos a publicar nada por internet (aún no, por lo menos). Para nuestro ejemplo estamos ejecutando Ubuntu 16 64 bits al cual le instalamos Chromium 59 y en la barra de direcciones escribimos lo siguiente:

chrome://extensions/

Luego presionamos Intro o Enter y veremos algo muy parecido a esto:

Chromium instalar y configurar extensiones
Chromium instalar y configurar extensiones

En letras verdes os indicamos dónde “clickar” para activar el modo de programador, se os habilitan tres botones pero el primero de izquierda a derecha es el que nos interesa, el que pone “CARGAR EXTENSIÓN SIN EMPAQUETAR” ya que le vamos simplemente a indicar la carpeta que a tal efecto creamos al comenzar este tutorial. Dice que es “sin empaquetar” porque para publicar nuestra extensión en internet debemos comprimirla en un formato específico y con una herramienta específica que no solamente ahorra tamaño sino que también agrega seguridad, pero no es tema de este tutorial, allí teneis los enlaces si quereis estudiarlos a fondo.

KS7000_ConoceTuIPv4 instalado en Chromium
KS7000_ConoceTuIPv4 instalado en Chromium

Así veremos cuando está instalada nuestra extensión, notad el icono al finalizar la barra de direcciones al cual al hacerle click nos muestra lo siguiente:

KS7000_ConoceTuIPv4 ventana emergente
KS7000_ConoceTuIPv4 ventana emergente

En esa ventana pequeñita es que se “ejecuta” nuestra página web con el enlace deseado, pues bueno, click y listo, se abre una pestaña nueva (ya que usamos el target “_blank”) y vamos a un dominio cuyo único trabajo es devolver la dirección pública IPv4 de nosotros los internautas. ¡Felicidades, hemos creado nuestra primera extensión!

Posibles problemas.

Seguimos insistiendo con las API‘s: si tenemos algún error en nuestro código, “una metida de pata”, el Chromium nos indicará y animará a seguir intentando; en este ejemplo a propósitos omitimos unas comillas de apertura, es decir, no la pusimos por pares y al cargar nos indica esto:

KS7000_ConoceTuIPv4 mensaje de error en comillas de apertura
KS7000_ConoceTuIPv4 mensaje de error en comillas de apertura

El mensaje indica que es un token desconocido, pues claro, no está bien delimitado el elemento y asume que queremos declarar un dichoso token: ¡todo esto por una simple comilla doble que omitimos!

Usando guiones JavaScript.

Recordemos que JavaScript lo podemos ubicar tanto dentro de un archivo html como en un archivo aparte js que sea llamado, desde luego, el fichero html. Ambos métodos son soportados por las extensiones en Chromium y vamos a revisar las dos opciones.

Guiones JavaScript internos.

Primero eliminamos la extensión que creamos en Chromium y vamos a agregar el siguiente guión JavaScript justo en la cabecera <head>:

 <script>alert("Aviso de JavaScript");</script>

A continuación reinstalamos desde nuestra consabida carpeta y hacemos click en el icono de la extensión instalada (si no os funciona, revisad de nuevo bien desde el principio de este artículo) y lograremos ver el siguiente aviso que os lo resaltamos en color verde:

KS7000_ConoceTuIPv4 JavaScript error
KS7000_ConoceTuIPv4 JavaScript error

Cuando hacemos click en diho botón veremos algo parecido a esto:

KS7000_ConoceTuIPv4 hash error
KS7000_ConoceTuIPv4 hash error

¿Qué ha sucedido aquí? Pues simple y llanamente que Chromium tiene ciertos requisitos de seguridad basados en recomendaciones de la W3C a fin de proteger la integridad de nuestro software. Para que se pueda ejecutar algún guión JavaScript insertado en un fichero HTML debemos calcular el hash (tenemos un tutorial que explica este tema) del fichero en cuestión en insertarlo en el manifiesto mediante un comando específico.

Para ello ya tenemos la mitad del trabajo hecho: el cálculo del hash lo hace Chromium sin siquiera pedirselo, así que lo aprovechamos para agregarlo en manifest.json y la idea es que al declararlo se obliga a compararlo con el generado al archivo HTML y si ambos coinciden se considera que no ha habido alteraciones a nuestro trabajo por parte de terceras personas con buenos o malos propósitos.

Debemos entonces incluir estas lineas en el manifiesto:

"content_security_policy": "default-src 'self' 'sha256-jLjrqnmi4O/pyY5/8e4eXAPbFQ6Vq8j76usKTBjmtb4='),

Recargamos con CTRL+R y repetimos el proceso, y ahora logramos ejecutar con éxito:

KS7000-ConoceTuIPv4 mensaje de JavaScript
KS7000-ConoceTuIPv4 mensaje de JavaScript

Para que tengamos presente la seguridad, si cambiamos un solo caracter de “aviso.html” inmediatamente Chromium dejará de ejecutar cualquier script que haya dentro del archivo. Para poder ejecutarlo de nuevo, debemos volver a actualizar el hash, pero surge la pregunta ¿y si el atacante también modifica el hash dentro del manifiesto? Si estamos en nuesstros propios ordenadores pues esto es más que dificil que suceda, un atacante no va a invertir tiempo y esfuerzo para malograr un solo ordenador, es lógico que busque atacar cientos o miles de computadoras así que el obejtivo sería un repositorio en internet y allí interviene lo que comentamos: para “subir” nuestra aplicación para se repartido por internet no solamente la debemos comprimir, SINO QUE TAMBIÉN LE TENEMOS QUE AGREGAR UN HASH AL ARCHIVO COMPRIMIDO (recordad la herramienta crxmake).

Para comprobar lo que afirmamos, solo basta modificar un solo caracter en el fichero aviso.html, nosotros le agregamos par de símbolos de admiración en el mensaje y aunque no afecte para absolutamente nada la seguridad de nuestro equipo de igual manera se muestra la línea que ha sido modificada (o, en la vida real “hackeada”), mirad:

KS7000_ConoceTuIPv4 modificado y el hash es distinto del registrado
KS7000_ConoceTuIPv4 modificado y el hash es distinto del registrado

Como nota curiosa, ya logramos que el guión se ejecute pero eso es solo lo que hará Chromium, es decir, el archivo aviso.html no será mostrado pero poco importa para nosotros porque simplemente estamos aprendiendo a programar, por ello nos olvidaremos de incluir una instrucción de este tipo que llamamos modal. Una ventana modal es aquella que se posesiona del enfoque de una aplicación y la única manera de continuar es obedecer la instrucción que ordena. Para que aprendamos los guiones que se guardan en un fichero aparte, externo a un fichero html, debemos presentar los conceptos de ejecuciones síncronas y asíncronas.

Guiones síncronos y asíncronos.

La principal diferencia entre ambos métodos estriba que mientras el método síncrono detiene su ejecución y espera el resultado o liberación de recursos, el proceso asíncrono se ejecuta por sí solo y va de manera independiente (interactue o no con el proceso que le dio origen). Se pudiera decir que ambos procesos “padre” e “hijo” deberían de alguna forma comunicarse y esto se debe hacer por medio del entorno de desarrollo o IDE, por sus iniciales en inglés de “Integrated Development Environment” o Ambiente de Desarrollo integrado, lo cual simplifica enormemente nuestro trabajo de programación ya que nos permite abstraernos en programar solamente sin importar el hardware o sistema operativo utilizado (si se quiere lo podríamos ver como “aislado por capas” como lo es el modelo OSIpara las redes de ordenadores).

Generando un proceso asíncrono.

Vamos entonces a modificar nuestro fichero “aviso.html” de la siguiente manera, resaltado en verde los cambios:

<!doctype html system "about:legacy-compat">
<html lang="es-419">
  <head>
    <meta charset="UTF-8">
    <title>KS7000</title>
  </head>
  <body>
    <h1>KS7000_ConoceTuIPv4</h1>
    <button id="conoceIPv4">¡Conoce tu dirección IPv4!</button>
    <p id="IPv4"></p>
    <script src="emergente.js"></script>  </body>
</html>

¡ IMPORTANTE ! : declarad vuestro guion externo en JavaScript DESPUÉS de los elementos, de lo contrario arrojará un error “null” indicando que los elementos no existen. Esto es así debido a que el analizador “parser” va de arriba hacia abajo, línea por línea, y el proceso asíncrono que lanzamos debe tener con qué trabajar. En este caso hay dos elementos que “pasaremos”: el botón identificado como “conoceIPv4” y el párrafo sin texto o “en blanco” identificado como”IPv4″.

Ahora vamos a crear nuestro elemento escrito en JavaScript. un guión que, por ahora, simplemente colocará un mensajito de texto en el párrafo identificado como “IPv4”:

document.getElementById("conoceIPv4").addEventListener("click", buscaIPv4);
  function buscaIPv4() {
    document.getElementById("IPv4").innerHTML = "vuestra IPv4 es:";
  }

Como veis es algo bien sencillo:

  • En la primera línea declaramos que al documento identificado como “conoceIPv4” le agregue un evento que esté en función de si el usuario hace click en el botón y que ejecute la función “buscaIPv4”.
  • A su vez la función buscaIPv4 POR AHORA lo único que hace es sustituir al elemento (párrafo) con el identificador “IPv4” y lo sustituya con el mensaje “Vuestra IPv4 es:”.

Al guardar y recargar con CTRL+R las extensiones instaladas va a volver a mostrarnos el mensaje de que los hash NO coinciden, copiamos el hash actualizado y lo pegamos en el fichero manifiest.json para volver a recargar y ejecutar, podréis observar algo muy parecido a esto:

KS7000_ConoceTuIPv4 mensaje de encabezado
KS7000_ConoceTuIPv4 mensaje de encabezado

¡LISTO, HEMOS CREADO UN PROCESO ASÍNCRONO! MUY FÁCIL, ¿CIERTO? 🤓

Creando

Comprobando compatibilidad en Mozilla Firefox.

Por medio de la cuenta Twitter de un desarrollador web de Mauritania tuvimos la excelente oportunidad de revisar cómo se desarrolla una extensión en Mozilla Firefox (versión 45 o superior) y además cómo preparse para presentarla al público, todo muy detallado y bien pensado.

Como Chromium y Firefox ambos comparten el entorno de programación chrome hace que compartan la misma estructura de datos pero se “llega” de diferente manera. Primero debemos introducir en la barra de direcciones el siguiente comando:

about:debugging

Presionamos la tecla intro y seleccionamos complementos y hacemos click en el botón “Cargar complementario temporario” (sí, suena extraño en castellano pero si queremos colaborar con las traducciones, pues las puertas están abiertas). Seleccionamos la carpeta con nuestro mini proyecto y listo ¡a comprobar!

KS7000_ConoceTuIPv4 ejecutado en Mozilla Firefox
KS7000_ConoceTuIPv4 ejecutado en Mozilla Firefox

Fuentes consultadas.

En idioma francés.

En idioma italiano.

En idioma inglés.

Calculando factoriales de números grandes

El día de ayer por medio del perfil de línea de tiempo del Doctor Juan González observamos el interesante artículo tutorial sobre Python publicado por Juan J. Merelo Guervós el cual incluye retos de programación. Ni tardo ni perezoso, a pesar de llegar cansado a mi hogar, y tras una vigorizante taza de café negro con leche de avena sin azúcar nos dimos a la tarea de practicar algunas cositas para mantener el cerebro en forma y al día con las novedades en programación.

Calculando el factorial de un número.

Definición.

No vamos a hacer esta entrada muy profunda, ya que debemos ir a trabajar para ganarnos el pan de cada día, directo y rápido: el factorial de un número viene expresado por la multiplicación sucesiva de sus antecesores, uno a uno, hasta llegar a uno y se denota por ” n! ” ; así, por ejemplo 5!= 5 x 4 x 3 x 2 x 1 = 120 (las equis indican multiplicación).

El reto.

Pues arroja el guante el sr. Merelo con una función recursiva escrita, por supuesto, en lenguaje Python para calcular un factorial y tras ensayo y error llegamos a una satisfactoria y muy parecida a la ya famosa y escrita por todos lados en internet (para ser honestos en algún momento vimos esta función pero no recordabamos… hasta que el buscador DuckDuckGo acudió en nuestra ayuda, un asistente tan capaz -en memoria- como todas las asistentes que tuvo Albert Einstein -que en paz descansen, Valentine Bargmann y el Doctor Einstein-).

Para ilustraros cómo funciona, aprovechando nuestro mundo tecnológico –y añorando el gis y el pizarrón- os colocamos un gif animado tomado de penjee.com, un sitio web dedicado también a la enseñanza de Python:

Función factorial animada tomada de penjee.com
Función factorial animada tomada de penjee.com
def factorial(num):
  if num == 1:
    return 1
  else:
    return num * factorial(num - 1)

Calculando el factorial de un número grande.

Factorial, fórmula y definición
Factorial, fórmula y definición

Hasta acá todo muy bien, pero el reto no finalizaba allí, una segunda pregunta era ¿qué tal calcula los números grandes? Como bien podéis imaginar, el multiplicar y multiplicar en ordenador pues en algún momento se nos agota la memoria suponíamos nosotros… pues que aquí está la pega del asunto, tras calcular el factorial 120! de manera fácil (en Wikipedia en inglés denotan que normalmente el máximo factorial que se puede calcular con un procesador de 64 bits en una variable de tipo entero es 20! –ya nosotros hemos comentado el poder de cómputo de los procesadores y sistemas operativos de 64 bits-) pues nos envalentonamos a ir “al infinito y más allá”.

python factorial.py con n = 120 (ciento veinte)
python factorial.py con n = 120 (ciento veinte)

Siendo así la cosa le establecemos a 1200 (un mil doscientos) a la función de marras y nos arrojó este lindísimo mensaje de error que os mostramos:

python factorial.py con n = 1200 (mil doscientos)
python factorial.py con n = 1200 (mil doscientos)

Pero leyendo nos percatamos que el problema no es el desbordamiento de memoria, no,  el desbordamiento es un error en la profundidad de recursión:

RecursionError: maximum recursion depth exceeded in comparison

El contrareto.

Ya esto se salía del reto impuesto, es un contrareto que nos presenta Python pues claro, en un entorno de programación uno debe siempre imponer límites considerando que aún no ha llegado la computación cuántica (y aún así ésta tiene límites en este universo). Indagando, y hay bastante material sobre el tema, llegamos a la librería sys encargada de manejar tales asuntos y de hecho el manual en línea de Pyton nos advierte:

Set the maximum depth of the Python interpreter stack to limit. This limit prevents infinite recursion from causing an overflow of the C stack and crashing Python. The highest possible limit is platform-dependent. A user may need to set the limit higher when she has a program that requires deep recursion and a platform that supports a higher limit. This should be done with care, because a too-high limit can lead to a crash.

Que traducimos al castellano:

Establece el límite de la profundidad máxima de la pila del interprete Python. Este límite previene una recursión infinita ocasionando un desbordamiento en la pila (del lenguaje) C y la consecuente falla de Python (Dios nos ampare que alguien crea que Python es falible†). El límite más alto posible es dependiente de la plataforma empleada. Un usuario puede necesitar ajustar el límite superior cuando tenga un programa que requiera una mayor recursión y la plataforma que lo soporta lo permita. Esto debería hacerse con cuidado porque un límite muy alto puede conducir a un fallo (Dios nos ampare que alguien crea que Python es falible†).

†(Nota del traductor en tono de sarcasmo).

Python recursion limit get and set
Python recursion limit get and set

O inventamos o erramos.

Don Simón Rodríguez: "Inventamos o erramos".
Don Simón Rodríguez: “Inventamos o erramos”.

Como nuestro insigne Don Simón Rordríguez nos legó, debemos inventar y a lo sumo fallar (y reintentar y así sucesivamente hasta lograr inventar) nosotros pensamos ¿Y si establecemos el límite superior de la pila de procedimientos (límite de recursión) precisamente de manera recursiva? 🤔

Pues acá vamos entonces:

import sys
def factorial(num):
  '''Return large factorial by Jimmy Olano Sayago
               (GNU General Public License v3.0) '''
  if num<=1:
    return 1
  else:
    sys.setrecursionlimit(sys.getrecursionlimit()+1)
    return num * factorial(num - 1)

file = open('large_factorial_result.txt', 'w')
cad = factorial.__doc__
file.write( cad )
file.write( ' factorial(21700): ' )
file.write( str( factorial( 21700) ) )
file.close

Al tener nosotros establecida la función, por tanteo y utilizando un procesador AMD A8-6600K APU (64 bits, 4 núcleos y 8 gigabytes en RAM) llegamos un valor de 21700! el cual ocupa 86400 digitos. Esencialmente el guion que hicimos basados en la clásica función recursiva de cálculo factorial es aumentar el límite de pila de Python de manera recursiva para luego abrir un archivo de texto y guardar allí el resultado.

El delicado tema de los typos de variables y la memoria disponible.

Consultamos muy diversos reportajes sobre el tema del manejo de la memoria y las variables pero el que fue revelador para nosotros es uno escrito hace más de once años pero que goza de plena vigencia: una comparación sobre cómo trabajan las variables los lenguajes C y Python.

Tiene su teoría y abunda su práctica y probamos los diferentes ejemplos y nos resultó en valore comprobatorios contra lo que se afirma en dicha entrada pero la conclusión es tan excelente que se las traemos en idioma inglés y la traducimos al castellano:

Python removes this confusion, there is only the integer object. Does it have any limits? Very early versions of Python had a limit that was later removed. The limits now are set by the amount of memory you have in your computer. If you want to create an astronomical integer 5,000 digits long, go ahead. Typing it or reading it will be the only problem! How does Python do all of this? It automatically manages the integer object, which is initially set to 32 bits for speed. If it exceeds 32 bits, then Python increases its size as needed up to the RAM limit.

La traducción hecha por nosotros:

Python elimina esta confusión (de variables), hay solo el objeto entero. ¿Tiene algún límite? Muy tempranas versiones de Python tuevieron un límite que luego más tarde fue removido. Los límites ahora son establecidos por el monto de memoria que usted tenga en su computadora. Si quiere crear un entero astronómico de 5 mil dígitos, ¡adelante! ¡Escribirlo o leerlo será el único problema! ¿Cómo Python hace todo esto posible? Pues automáticamente dirige el objeto entero, el cual inicialmente estaba configurada a 32 bits por motivos de velocidad. Si excede los 32 bits, entonces Python incrementa su tamaño tanto como se necesite hasta llegar al límite de la memoria RAM.

Así como lo podéis leer, en el año 2006 se consideraba “astronómico” una cifra de 5000 dígitos, ¡PUES HE AQUÍ QUE CALCULAMOS UN FACTORIAL CON 86400 DÍGITOS! Para nosotros es todo un logro digno de dedicarle una entrada y una pequeña nota en las Wikipedia(s).

Sometido a consideración por la comunidad de programación y comunidad matemática.

De inmediato subimos el guion y su resultado (utilizando el idioma inglés) a Gist mantenido en línea por GitHub.com (¡gracias!) y “tuiteado” con la etiqueta #Python y #1linepy tal como recomienda el sr. Merelo:

Experimento social.

Como experimeto social hemos cometido una torpeza en la fórmula cuando establecemos:

if num<=1:
  return 1

El objetivo es detectar cuántas personas realmente analizan nuestra propuesta y nos hacen llegar sus observaciones (se especula que el mismísimo Leonardo DaVinci codificaba mal sus planos a propósito por si caían en manos enemigas) ya que el cálculo de factoriales está supeditado al campo de los números positivos, ya sean reales o imaginarios (esto es así porque el cálculo factorial es clave en la determinación de combinaciones y permutas, todas ellas en el campo de los números positivos).

También hemos publicado en Wikipedia en inglés nuestra experiencia (y próximamente en castellano, francés, italiano, portugués, alemán y ruso en la medida de lo posible y de nuestro tiempo libre) para determinar cuales sociedades unidas por un idioma común aceptan o rechazan nuestra propuesta (cada idioma Wiki tiene sus wikipedistas que algunas veces nos han “echado para atrás” nuestras ediciones por diversos motivos variopintos).

 

Conclusión: no hemos llegado aún al infinito, menos más allá.

Una inquietud que tenemos es la gran cantidad de ceros al final del resultado y una cosa que nos tranquiliza es la serie de resultados hasta 20! que va aumentado la cantidad de ceros a la derecha. Lo lógico es que si estamos multiplicando pues “corremos la coma hacia la derecha” y se debe, desde luego, rellenar con ceros para ello.

Aún falta por determinar hasta qué punto alcanza nuestro hardware su límite, podremos hacer un ciclo “for” que arranque con este último valor de 21700! e irlo incrementando y guardando en archivos cuyos nombres tengan el valor calculado apara identificarlos hasta que simplemente falle Python, ¡PERO ESPEREN, HAY MÁS!

Pensamos que arrancando nuestro sistema operativo Ubuntu 16.04 LTS en modo terminal, sin cargar interfaz gráfica y “tumbando” los servicios diversos -Apache server, MySQL, etc.- y los más que se puedan de systemd ganaremos más memoria y compararemos resultados a ver si influye y si es así, cuánto influye, ¡SOMOS TODO OÍDOS A VUESTRAS IDEAS AL RESPECTO POR MEDIO DE NUESTRA CUENTA EN TWITTER @KS7000!

Fuentes consultadas.

En idioma castellano.

En idioma italiano.

En idioma inglés.

Marp a primera vista

Nos empeñamos en realizar tutoriales pero en este caso vamos a realizar una simple revisión a un software novísimo: Marp. Esta entrada viene a colación por un “tuit” del sr. Aitor León desde Sevilla, España donde hace un autorecordatorio sobre un software del cual nosotros no habíamos escuchado antes y que nos llamó la atención porque le aplicó la etiqueta #MarkDown:

Nosotros con mucho respeto le preguntamos qué era ese programa y amablemente nos respondió:

Ni tardo ni perezosos indagamos y he aquí lo que pudimos aprender, lo cual humildemente compartimos con el mundo entero de habla castellana.

Inicio y desarrollo de Marp.

Un paso para comenzar.

Ya bien dice el refrán que todo viaje, por muy largo que sea, comienza con un solo paso: el 11 de febrero de 2016 (hace una gran cantidad de tiempo en términos de ordenador japonés) se escribió el comienzo de Marp, el cual originalmente se llamaba MDSlide en su versión 0.0.1.

1
2
3
4
5
6
7
{
"name": "mdslide",
- "version": "0.0.0",
+ "version": "0.0.1",
"description": "Presentation writer with markdown",
"main": "main.js",
"scripts": {

Desarrollo: nace Marp.

En mayo de 2016, luego de duro trabajo, MDSlide se transforma en Marp y la numeración de versiones correlativo corresponde a V0.0.6; al cambiar de nombre nace un repositorio nuevo y de MDSlide no quedan rastros… dice uno porque bien sabemos que el protocolo Git es distribuido y por ahí en algún disco fijo debe haber una copia, je, je, je. El logotipo es el ahora conocido y la verdad ya estaba bastante maduro: soporte para emoji, ecuaciones matemáticas (eso nos impresiona) e imágenes (recordad que se basa en MarkDown: se trabaja con teclado).

Ruta de trabajo.

Para octubre de 2016 se retoma el desarrollo debido a que escuchando las sugerencias de los usuarios se replantea todo y liberan la versión 0.0.9 y se declara un plan de trabajo para liberar la tan ansiada versión 1.0 . También debemos tomar en cuenta que Electron, el entorno de programación utilizado, también ha sido actualizado y eso “empuja” a Marp en cierta medida y a pesar de suficientes “pull requests” (copias del código fuente modificado por terceros que lo devuelven mejorado y/o con sugencias) que recibe el sr. Hattori, él ratifica que sigue en las riendas del proyecto y espera mejorarlo mucho gracias a sus usuarios y colaboradores. Pero en este punto reconoce que el modo de presentación es la parte más difícil y es algo que aún no han logrado pulir, pues es esa la característica que estuvimos buscando nosotros y no vemos por ningún lado (más adelante mostraremos su uso con ejemplos en castellano). La “discusión” es viva y candente (en inglés) e incluso se le llega a comparar con software privativo que lleva décadas en el mercado.

Última versión a la fecha de escribir este artículo.

En noviembre de 2016 liberan la versión 0.0.1 que es la versión que descargamos y probamos pero al abrirlo nos encontramos con una versión compilada a lenguaje de máquina y con una extraña versión 1.3.8 ¿En qué momento nos perdimos… de algo? De todos modos no especulemos nada aún, en la parte del licenciamiento veremos bien si realmente es “software libre” o de “fuente abierta”.

Autoría.

Así nació Marp de las manos del Ingeniero de Software Web Yuki Hattori, graduado en « 公立はこだて未来大学 » (“Public Hakodate Future University”) y quien actualmente trabaja en la empresa “Speee, Inc.” en Tokio, Japón.

Ingeniero Yuki Hattori
Ingeniero Yuki Hattori

El Ingeniero Hattori maneja una gran cantidad de lenguajes de programación (vamos que desayuna PHP, merienda con CSS, almuerza con Ruby, la merienda de la tarde la pasa con Node y cena con Rails) y nosotros que pensábamos que algo programamos, pues nos quedamos cortos (44% en otros lenguajes de programación ¿cuáles serán? Acá hace algo con SVG dinámico y en este enlace lo podéis probar y modificar cortesía de Phil Maurer).

Yuki Hattori lenguajes de programación más utilizados
Yuki Hattori lenguajes de programación más utilizados

Licencia de uso.

El repositorio oficial de Marp lo podéis encontrar en este enlace, y de sus múltiples secciones hemos leído y analizado la información para el presente artículo, esparamos os sea útil en algún modo.

En junio de 2016 el proyecto tiene un mes con su nombre actual Marp y deciden colocar correctamente la licencia de uso que corresponde a la del Instituto Tecnológico de Massachusetts (MIT) la cual no puede ser un simple enlace web, se debe colocar el encabezado con el año y el nombre del autor para luego copiar fielmente la licencia de uso del MIT y luego, si se quiere, el enlace web correspondiente.

De hecho múltiples organismos conservan una copia de dicha licencia y la más socorrida es la de “The Open Source Initiative”; vale la pena recordar entonces que una cosa es software libre y otra cosa es código fuente abierto: para no ser puristas el software libre es más antiguo y solo tiene 4 reglas básicas (aunque ha evolucionado) y el código fuente abierto deriva su filosofía del software libre y tiene 10 reglas básicas.

En julio de 2016 se reconoce que el proyecto contiene un trabajo realizado con anterioridad y que también posee licencia de uso del MIT: Katex el cual está escrito en JavaScript y CSS para representar gráficamente las tediosas fórmulas matemáticas. Nosotros que estudiamos ingeniería mecánica y nos tocó estudiar matemáticas avanzadas damos fe del tremendo trabajo de presentar informes y no tener un software adecuado para ello. Da un poco de vergüenza decirlo pero era rapídisimo realizarlo de forma manuscrita y presentable en hojas blancas que lo horroroso que quedaban con las impresoras de matríz de punto y el software que disponíamos. Hemos progresado hasta el punto que hoy tenemos presentaciones en un lenguaje de marcación ligero y sencillo, que puede representar las matemáticas como son ¡y de paso se puede exportar a formato pdf, increíble!

En este mismo mes se decide retirar el anuncio de licencia de uso de underscore.js ya que no se sigue utilizando como componente.

Página web oficial de Marp.

En este enlace se tiene una presentación bien cuidada acerca del software y orientada a los usuarios normales, no programadores. Podemos ver su características, un enlace al repositorio, un enlace para descargarlo, una rápida introducción a su uso, una guía a ejemplos más avanzados y una declaratoria de licencia de uso. Lo que nos llama poderosamente nuestra atención es la inserción de dos objetos web que presentan por diapositivas a Marp, dichos objetos fueron hechos en Deckset -software hecho en Alemania-el cual está también basado en MarkDown… ¿casualidad? Bueno acá el software de fuente abierta supera al privativo, pues no exporta en formato pdf… y podremos agregarle funcionalidades que consideremos haciendole un “fork” y haciendo nuestro propio proyecto (conservando la licencia de uso del MIT, por supuesto).

“Instalando” Marp.

Pues que si llamamos “instalar” a descargar un archivo y descomprimirlo, vale, “cuela” como instalación. Esta entrada no es tan compleja como otras que hemos hecho que analizamos lo más a fondo que podemos su código fuente, pero no os preocupéis, no perderemos de vista a Marp en el futuro. Repetimos, el repositorio está en esta dirección.

Usando Marp.

Pilares fundamentales de Marp.

  • Escribimos en MarkDown las presentaciones (y también podemos ver el resultado del MarkDown).
  • Se pueden escoger temas y fondos de pantalla para las presentaciones.
  • Soporta caracteres UNICODE (mejor conocidos como emojis).
  • Se puden escribir ecuaciones matemáticas con hermoso estilo.
  • Se puede exportar a formato PDF.

Haciendo presentaciones en MarkDown.

Retrospectiva.

Admitámoslo: realizar presentaciones es tedioso para los que no tenemos el talento para los gráficos. Somos empedernidos usuarios de la ventana terminal y por eso nos agrada mucho el MarkDown y su simple sintaxis para obetener una apariencia básica del HTML… ¡Pero esperen, hay más!

Desde que Github popularizara el Git con su alojamiento gratuito para proyectos públicos (que de acuerdo a la licencia de uso que tengan tendrán diferentes clasificaciones) y agregaron el uso de MarkDown acompañando a los repositorios con su respectiva sección Wiki, que también utiliza cierto “sabor” de MarkDown, y ahora con una ligera variante podremos hacer presentaciones rápidamente sobre nuestro trabajo ya hecho pues… ¡BINGO! 🙌😎

Hala, manos a la obra.

Aunque entre las carpetas descomprimidas hay una llamada “locales” hay un archivo llamado es.pak cuyo contenido abrimos con gedit y está escrito en castellano, no hallamos opción para cambiar el idioma inglés. Revisando el código fuente no hallamos referencia a dichos archivos .pak (hay bastantes idiomas) lo que imaginamos es que son “paquetes”  o plantillas que se utilizan masivamente para internacionalizar nuestras aplicaciones… o simplemente será nuestra imaginación.

Dicho todo esto, os escribiremos en inglés las referencias que hagamos al programa Marp.

No nos afanéis buscando teclas de acceso directo -para hacer cualquier cosa- excepto las siguientes:

CTRL+NNew fileFichero nuevo
CTRL+OOpen...Abrir un fichero
CTRL+SSaveGuardar fichero
Mayús+CTRL+EExport slides as PDFExportar presentaciones a formato PDF
CTRL+WCloseCerrar programa
CTRL+ZUndoDeshacer acción
Mayús+CTRL+ZRedoRehacer acción
CTRL+XCutCortar selección
CTRL+CCopyCopiar selección
CTRL+VPastePegar selección
CTRL+ASelect allSeleccionar todo
F11Toggle full screenCambiar a pantalla completa

Marp, como es de esperarse, utiliza la misma extensión de fichero de los documentos MarkDown: .md (tal vez presentemos algún vahído porque estamos bien acostumbrados a que las presentaciones tienen sus propias extensiones según el software que las manipule).

Lo primero es abrir un archivo nuevo, vamos al menú desplegable “File” -> “New file” (o pulsamos las teclas CTRL+N). Sin más preámbulo se abre un “lienzo” de trabajo presto a escribir en el. En este lienzo a la izquierda escribimos nuestro código y a la derecha veremos inmediatamente nuestro trabajo de tres maneras distintas:

  • En modo de presentación, diapositiva por diapositiva (modo por defecto).
  • En modo de presentación, diapositivas en hilo o “carrousel”.
  • En modo MarkDown, tal como se vería al publicarla en la página web de GitHub, por ejemplo (¡interesante!).

Títulos y subtítulos.

Inician con un símbolo numeral “#” seguido de un espacio y el texto para título principal y agregando dos o más numerales juntos -sin espacios- los subtítulos correspondientes (hasta un máximo de seis subniveles):

Marp títulos y subtítulos.
Marp títulos y subtítulos.

Nota 1: Marp como buen intérprete del MarkDown “original” soporta el uso de “=” y “-” (uno o más) en la línea inmediatamente inferior del texto para mostrar un encabezado de primer y segundo nivel. Pero si necesitamos de un  tercer nivel necesitaremos tres numerales “###”… así que no vale la pena este método os aseguro.

Nota 2: Marp aplica a las imágenes un “realzamiento” su utilizamos numeral (es) delante de la declaración de imágenes, sin embargo “=” y “-” no funcionan en estos casos (no le busquen lógica a esto, por favor, no sabemos si es un “bug” o es algo hecho a propósito).

Realizando una segunda diapositiva.

Como véis el código MarkDown funciona y no es obejtivo de esta entrada mostraros su sintaxis por lo tanto vamos a enfocarnos en los comandos propios de Marp, que son apartes del MarkDown con el propósito de presentar nuestras diapositivas.

Tal como insertamos una línea horizontal en Markdown (tres guiones seguidos al principio de una línea) así agregaremos una segunda diapositiva, cuidando de dejar una línea en blanco antes y después:

Marp inserción de nueva diapositiva
Marp inserción de nueva diapositiva

Enumerando las diapositivas.

Para agregar el número de diapositiva en la esquina inferior derecha solo debemos agregar el siguiente código.

<!-- page_number: true -->

A partir de la diapositiva donde insertemos la orden serán numeradas hasta el final, si queremos que todas están numeradas la posicionaremos en la primera diapositiva; por el contrario, si queremos que una diapositiva en particular NO sea numerada modificaremos la directiva anterior agregandole un asterisco para indicar que se le aplique solo a esa diapositiva. Por supuesto, usaremos el valor verdadero o falso a nuestro gusto o necesidad.

Marp numeración de diapositivas
Marp numeración de diapositivas

Directivas globales y directivas locales.

Lo que acabáis de ver “encerradas” entre comentarios tipo HTML “<!— comentario —>” por supuesto no se visualizan en nigún navegador o intérprete de MarkDown sin embargo Marp obtiene sus instrucciones de allí en el formato de una instrucción por línea separadas por dos puntos “:”. Dichas instrucciones son llamadas directivas y como vimos serán globales -para todas las diapositivas, el documento completo- o solo para la diapositiva donde se encuentre la directiva que establezcamos siempre y cuando sean antecedidas por un asterisco.

Dado el caso que nos equivoquemos en la sintaxis pues simplemente Marp no las toma en cuenta ni ejecuta y no arroja ningún tipo de mensaje de excepción.

Directiva “$theme” y “template”.

Marp soporta plantillas predeterminadas para nosotros dedicarnos a lo valioso de escribir los datos en las diapositivas, lo demás son “adornos de repostería”. Al momento de escribir esto estaba disponible el tema gaia y de manera adicional con la directiva template:invert se tiene una inversión en los colores. Esto queda guardado en el documento de diapositivas para que Marp automáticamente la muestre al volver abrir el documento. Nota: si por el menú desplegable escogemos “View”->”Theme”->”default” -o cualquier otro tema que haya disponible- Marp obviará la directiva que hayamos establecida dentro de la diapositiva y mostrará la que le hayamos ordenado. Verbigracia:

Marp directiva theme y template
Marp directiva theme y template

Marp directiva “footer”.

Con esta directiva podremos establecer una frase en pie de página ya sea en todas las diapositivas o solo en la que le coloquemos la directiva, recordad el asterisco hace a la directiva local, mirad:

Marp directiva footer
Marp directiva footer

Directiva $size

Esta directiva puede ser confusa porque se refiere a tamaño sin embargo presenta también unos valores que indican proporción pero si buscamos la lógica ambas son excluyentes mutuas y explicamos por qué: todo depende si nuestra presentación será por pantalla (primera opción para el 99% de los casos, vamos que hablamos de presentaciones por diapositivas). El otro asunto es si necesitamos imprimir dichas presentaciones.

  • Para la proporción tenemos “4:3” predeterminado para monitores normales y la mayoría de proyectores traen este valor por defecto y “16:9” para monitores “multimedia” -llamados así porque las películas son grabadas en esa proporción panorámica-.
  • Para el tamaño  de papel tenemos desde A0 hasta A8 y B0 hasta B8, os adelantamos que el “tamaño carta” viene a ser A4 (mirad abajo en las fuentes consultadas el resto de los medidas de papel).
  • Por los dos puntos anteriores es que decimos que son mutuamente excluyentes.
  • Esta directiva solamente es global, recomendamos declararla al principio para un orden efectivo (hicimos pruebas y el asterisco lo que hace es inutlizarla).
  • Es indiferente que usemos mayúsculas o minúsculas en los tamaños de papel.
  • Marp lee de izquierda a derecha y el primer tamaño válido de papel o proporción lo aplica, el resto de los caracteres lo desecha (debería NO aplicar el formato o al menos indicar la excepción, pensamos).
  • No conseguimos hacer funcionar el prefijo documentado “-portrait”, recordad que aún es un software en desarrollo y sus gazapos tendrá.
Marp directiva $size
Marp directiva $size

Directivas $width y $height.

De necesitar un tamaño personalizado de papel, estas dos directivas son las adecuadas al caso y ambas heredan todo de la directiva $size por ello no os ponemos gif animado aunque si os podemos decir que si que funciona (¡vamos, animaros a descargar y probar Marp!) y las opciones disponibles son:

  • px: píxeles por defecto, no es necesario colocarle “px”.
  • Por la razón anterior las siguientes unidades debéis colocarla juntitas sin espacio(o)s o si no lo interpretará como píxeles.
  • cm: centímetros.
  • mm: milímetros.
  • in: pulgadas “inches”.
  • pt: puntos.
  • pc: picas.

En realidad dichas unidades son las utilizadas por CSS excepto em (tamaño de fuente) y “%”; abajo en “Fuentes consultadas” (en idioma portugués) tenéis un enlace si queréis aprender más por vuestra cuenta.

Directiva “$prerender”.

Antes de entrar de lleno con las imágenes os presentamos esta directiva especialmente hecha para indicarle a Marp que haga un preproceso de las imágenes de fondo en el caso de que éstas sean muy grandes, aligera el proceso con una carga previa de datos.

<!– prerender: true –>

Comando para mostrar imágenes.

Así como lo leeís, ya finalizamos las directivas y volvemos a los comandos de MarkDown en este caso os indicamos lo siguiente:

  • Para comenzar a insertar una imagen comenza por una línea en blanco donde colocareís ![]( “”) tal cual, incluyendo los paréntesis, son 8 caracteres en total.
  • Dentro de los corchetes rectos (paréntesis rectos) colocaréis el texto alterno si no se puede cargar la imagen, podéis dejarlo vacío pero el uso de los corchetes es obligatorio, de lo contrario no muestra imagen alguna.
  • Dentro de los paréntesis (curvos) pero fuera de las comillas dobles el nombre del fichero de la imagen (si reside en la misma carpeta de donde ejecutásteis Marp o una URL válida, local o internet).
  • La razón de utilizar una imagen desde internet es para mostrar los últimos valores o cifras relacionados con el tema de la presentación, de lo contrario llevad tus imágenes junto con el documento Marp
  • Entre la URL de la imagen y las comillas dobles debéis dejar un espacio -el mismo que consideramos al principio en el conjunto de 8 caracteres iniciales de declaración.
  • Dentro de las comillas dobles -que sí son opcionales- podemos colocar una breve descripción acerca de la imagen o una frase nemotécnica que podramos visualizar al pasar el puntero por encima de la imágen, tras lo cual al cabo de menos de un segundo se colocará una pequeña ventanita en blanco sobre negro con el texto que coloquemos.
Comando para mostrar imágenes de fondo.

Muchas personas querrán, en vez de utilizar o crear tema alguno, simplemente fijar una o más imágenes como fondo en las presentaciones. He aquí que Marp se toma la ligera licencia de tomar la sintaxis de las imágenes -en MarkDown– con la excepción que en los corchetes rectos colocamos el comando [bg]  y por supuesto la URL local o remota de la imagen en sí. Dentro de los corchetes rectos acompañando a “bg” más un espacio podemos colocar un procentaje para redimensionar la imagen e incluso podemos colcoar varias imágenes siempre y cuando los porcentajes sumen 100% para garantizar visibilidad completa de cada imagen. El comando “bg” no soporta mayúsculas, disfrutad nuestras pruebas:

Marp fondo de diapositiva
Marp fondo de diapositiva
Comandos para mostrar caracteres emoji.

Si se sorprenden por haber colocado los emoji como subsección de las imágenes preparaos a recibir una historia bien larga… vamos a tratar de resumirla lo mejor posible.

Por allá en los años ochenta cuando nosotros comenzamos a manipular computadoras y luego entramos a estudiar en la Universidad de Carabobo… ¡EA, ¿PARA DÓNDE VAÍS, QUEDAROS Y ESCUCHAD! 😈

…👴 os contábamos que apenas teníamos computadoras de 16 bits XT y luego vinieron las de 32 bits -286, 386, etc- y en los años 90 se populariza -y hay hardware para manejarlo- el UNICODE que no es más que la representación codificada y gráfica -dibujada con papel y lápiz- de unos 65 mil y pico de caracteres- de la mayor parte de los alfabetos ideados por la humanidad. Allí se tuvo previsión de crear unos símbolos que representaban caras con diferentes estados de ánimo y objetos comunes, el gran problema era dibujarlos por pantalla Y ESO AÚN HOY EN DÍA ES DIFÍCIL DE HACERLO ¿por qué decimos esto?

Está bien, los sistemas operativos modernos manejan los códigos extendidos de UNICODE, con tan “poderosos” aparatos que tenemos faltaba más, faltaba menos. Pero a nivel de hardware, de tarjeta madre, aún no hemos visto que tengan dicho UNICODE grabado en firmware, los asiáticos han hecho hermosos BIOS gráficos pero que en realidad lo que hacen es cargar en memoria un mini sistema operativo con interfaz gráfica para su idiomas basados en ideogramas: AÚN NO SUCEDE QUE EL CPU ENVIE A UN MONITOR CUALQUIERA EL CÓDIGO BINARIO DE UN CARACTER UNICODE (EXTENDIDO) Y EL MONITOR TENGA “MEMORIA” PARA SABER COMO SE DIBUJA ¿Nos seguís el hilo? {Nota: todo monitor e impresora de matriz de puntos tiene en memoria cómo dibujar los 255 caracteres ASCII originales, pero hasta allí llegan, e incluso las impresoras a inyección de tinta y láser ¡perdieron esa capacidad!}.

Más aún, la genialidad de Steve Jobs, el fundador de Apple Computer -hoy la empresa más poderosa del mundo, incluso por encima de Microsoft e IBM juntas- fue el poner en práctica el trabajo desarrollado por Xerox Palo Alto (empresa aliada mutua con Apple) de fuentes tipográficas: pequeñísimas imágenes que computadoras con la suficiente potencia pueden dibujar rápidamente en pantalla imágenes que nosotros identificamos como “letras”… ¿y todo este discurso para qué? 😕

Todo este discurso es para deciros que aún los sistemas operativos modernos NO POSEEN soporte nativo y por ende los navegadores web tienen que obtener de algún lado esas pequeñísimas imágenes que nosotros lamamos “letras” o,  para este caso, emoticons.

Repetimos, lo simplificamos lo más que pudimos, en serio, no somos licenciados en computación pero como nos tocó vivir esa experiencia en carne propia, la evolución de los ordenadores (y escribimos, que algo queda para la posteridad de las generacioens futuras) pero a ese nivel da este tema.

Volviendo al tema de los emoticons o emoticones para castellanizar el término, revisamos el código fuente de Marp y observamos que utiliza dentro de sus dependencias (a esto nosotros lo llamamos librerías dinámicas) algo llamado markdown-it-emojiy a su vez buscamos en el código fuente de ese software unos “comandos” que permitan especificar los emoji en Marp.

Para Marp un emoticon o emoji viene encerrado entre par de dos puntos “: :” y dentro, sin espacios viene la palabra clave con la cual se busca y se dibuja (imaginamos que al compilar Marp todas esas imágenes vienen a nuestro disco duro en el fichero ejecutable luego investigamos y nos dimos cuenta que a este proceso ELECTRON lo llama “Application Distribution“, con el archivo app.asar del cual podrán saber y entender su forma de almacenar la información en su propio repositorio).🤔

Ya para finalizar el tema de Marp y los emoticones, esos comandos o palabras claves (que no trae documentados cuántos ni cuales son) que os dijimos, los copiamos, encerramos entre “: :” y los pegamos en Marp para producir la siguiente captura (otra nota: los emoticones se ven afectados en tamaño si están precedidos como título “#”, notad eso):

Marb emoticon emoji
Marb emoticon emoji
:angry::blush::broken_heart:
:confused::cry::frowning:
:heart::imp::innocent:

---

:joy::kissing::laughing:
:neutral_face::open_mouth::rage:

---

:smile::smiley::smiling_imp:
:sob::stuck_out_tongue::sunglasses:

---

:sweat::sweat_smile::unamused:
# 😉

<!---
$size: A8
--->

Podéis obtener una lista ampliada, nemotécnica, en este enlace cuyo encabezado anuncia las páginas web y/o aplicaciones que utilizan esos emoji. Por ejemplo :cat: es más fácil de memorizar que U1F408, caracter unicode, y que funciona sin problemas con Marp. En dicha página hacéis click en el emoji que os guste y es copaido la palabra clave con su par de dos puntos, y pegáis en MArp. Un código que no veréis es el de GitHub :octocat: (combinación de pulpo con gato) así que no es una lista definitiva, por ahora.


Nota “final” sobre el tema🤓: estos emoticones que véis son los de WordPress, que Twitter tiene los suyos propios (acá está cómo enlazar el CDN a vuestras páginas web y/o aplicaciones web y acá un ejemplo de vista previa de las imágenes obtenidas que por curiosa coincidencia son los mismos del mapa de caracteres de Ubuntu 🤖 je, je, je)

 


Actualizado el domingo 11 de junio de 2017.

Una lista completa de los códigos nemotécnicos de Marp los encontraréis en esta dirección: https://github.com/markdown-it/markdown-it-emoji/blob/6a65f5183fe0145219805040988341bf76ade32e/lib/data/full.json

Ofrecemos disculpas por no haber investigado lo suficiente. Esa sí es una lista completa de los caracteres emoji y soportados por Marp porque forma parte de sus componentes y compilación.


Enlaces web.

Los enlaces web o hipervínculos en Marp los podemos declarar de forma implícita y explícita (forma recomendada):

  • De manera implícita: si escribís “http://” más un caracter cualquiera, Marp lo convierte de inmediato en un enlace a la derecha en la ventana de visualización. También cuela “www.” más al menos dos caracteres.
  • De forma explícita: como dicta el MarkDown: un par de corchetes rectos (opcionales) donde colocaremos el texto del enlace y un par de paréntesis (curvos) donde colocaremos el enlace web en sí mismo.
Marp enlaces web
Marp enlaces web

Antes de hablar de las ecuaciones matemáticas…

…debemos indicaros que si necesitamos mostrar el código fuente en MarkDown a nuestra audiencia debemos encerrarlas entre triple comillas simples y Marp los interpretará como texto simple, es decir, no lo “ejecutará”, no hará “parser”.

Marp mostrar código MarkDown a la audiencia
Marp mostrar código MarkDown a la audiencia

Ecuaciones matemáticas.

Y acá lo que nos apasiona de tanto en tanto: las matemáticas, especialment el cálculo infinitesimal. Para ello Marp tiene un suplemento que debemos ingresar entre par de símbolos de pesos (o lo que sería con el paso del tiempo como símbolo de dólar). Cualquier texto que escribamos lo representa tal cual pero si lo antecedemos de cierta sintaxis comenzaremos a escribir nuestras fórmulas (no os preocupéis, no nos extenderemos mucho a favor de vuestra paciencia).

Fórmula de Euler.
  • Claro, cualquier texto lo representa tal cual…
  • … pero si lo antecedemos con un “_” tendremos un subíndice.
  • Con “^” lo convertiremos en superíndice.
  • Para agrupar estos subíndices o superíndices los encerramos entre llaves “{}”
  • Para multiplicar términos: “\cdot”.
  • A “\cdot” le podemos agregar paréntesis para agrupar más términos.
  • Para mostrar tres puntos suspensivos: “\cdots”.
  • ¡También podemos combinar “\cdots()”!
  • Ya con esto podremos representar la famosa fórmula de Euler:
Marp formula de Euler
Marp formula de Euler

Nota: cada fórmula matemática debe ocupar una o más líneas completas, no podemos intercalar fórmulas en una línea, por ejemplo. Opinamos que debería hacerlo y hasta podemos clonar el repositorio y empezar a programar, para eso es el software libre.

Identidad de Euler.
Marp identidad de Euler
Marp identidad de Euler

Símbolos y signos.

Es una lista larga, larguísima como la matemática misma pero los más comunes símbolos matemáticos tienen sus propios códigos:

  • Para representar 𝛑 usamos “\pi”.
  • Para representar 𝚽: “\phi”-
  • Para 𝛉: “\theta”
  • Infinito: “\infty”.

Operadores matemáticos simples y avanzados:

  • División: “\div”.
  • Fracción: “\frac{}” -colocamos el numerador entre llaves y el denominador a continuación.
  • Sumatoria: “\sum” -la podemos combinar con superíndices y subíndices.
  • Raíz cuadrada: “\sqrt” más el número -o llaves, o paréntesis.
  • Paréntesis grandes, ideales para encerrar fracciones: “\Bigl(” y “\Bigl)”.
  • Para representar integrales simples: “\int”, dobles “\iint”, triples “\iiint”, integral de superficie “\oint”.

Fórmula de cálculo de la constante e.

Marp cálculo de constante e
Marp cálculo de constante e

Exportar a formato PDF.

Probamos la exportación de archivos a formato PDF y no tuvimos ningún tipo de problema, si acaso un detalle que “no recuerda” los últimos archivos abiertos o guardados, “archivos recientes” les decimos. Incluso los emoticones fueron exportados y hermosamente dibujados -claro si originalmente fueron hechos en SVG nunca pierde calidad alguna al “pasar” de un lado a otro.

Conclusiones.

El software se ve realmente prometedor y aunque tiene la opción F11 pra verlo a pantalla completa no es lo mismo que un programa de presentación que se precie como tal: debe ser capaz no solo de usar las flechas de dirección del teclado para avanzar diapositivas sino que le falta aún programador de tiempo, música y lo más importante, ser capaz de detectar -y escoger- los múltiples monitores y/o proyectores que tengamos conectados a nuestro ordenador.

Esperamos os haya sido útil este vuestro -y nuestro- trabajo para la ampliación de conocimientos y saberes. 😉

Fuentes consultadas:

En idioma castellano:

En idioma inglés:

En idioma portugués:

En idioma japonés (nos disculpáis cualquier “fe de errata” al traducir):

@ObiJuan_cube

Bien merecido galardón O’Reilly para @ObiJuan_cube González

Cuando tuvimos que actualizar nuestros conocimientos sobre Diseño Asistido por Computadora (CAD) nuestra experiencia era limitada y amarrada al software privativo Autocad® y como estamos decididos a ser libres nos decantamos por Freecad para realizar nuestro trabajo. Comenzamos así nuestro aprendizaje, que sobre el tema abunda en internet pero quien de inmediato llamó nuestra atención por su trabajo estructurado y paciente fue  “ObiJuan” González y su Escuela de Padawan’s “CloneWars”. Por ello cuando tuvimos noticias de que se le había otorgado el premio de Google llamado O’Reilly Open Source Award en reconocimiento a su labor (aunque es tonto de nuestra parte) nos contentamos en sumo grado y de que no solamente el Software Libre esté en tan alto nivel en España sino que también el HARDWARE LIBRE está surgiendo en América tutelado por (a pocas personas llamamos por su título, y por sus títulos menos) el Ingeniero y Doctor Juan González Gómez.

 

Premio “O’Reilly 2017 Open Source Awards”

El jueves 11 de mayo en Austin (Estados Unidos), durante la celebración del congreso mundial OSCON, fue entregado el premio O’Reilly 2017. Fueron creados en el año 2005 por Tim O’Reilly y hasta el 2009 llevaban el prefijo Google-O’Reilly pero hasta la fecha de hoy simplemente lleva el nombre O’Reilly Open Source Award: un reconocimiento a los individuos por su dedicación, innovación, liderazgo y destacada contribución al código abierto.

El premio, creado y organizado por Google en colaboración con la factoría de Tim O’Reilly, desde el 2005, se entregó este jueves 11 de mayo en Austin (Estados Unidos) durante la celebración del congreso mundial OSCON, evento que reúne a toda la comunidad de ingenieros y desarrolladores de software y hardware libre.

Es así que ObiJuán se ha ganado su hito en la muy famosa Wikipedia (hasta que Skynet🤖 cobre conciencia de sí misma y borre nuestra adición de los ganadores del año 2017 en esa página, ja, ja, ja).

“ObiJuán” González Gómez.

Eterno empedernido de la saga de películas «La Guerra de las Galaxias “Star Wars”» -¡ejem! nosotros también 🤓- se autodenomina por este juego de pronunciación en inglés y castellano del Maestro Jedi de los films Obi-Wan Kenobi como ObiJuán (nosotros castellanizamos aún más las cosas con la inclusión del acento) este madrileño ejemplar comenzó sus andanzas …

¡Este blog no va de ciencias sociales! No somos biógrafos de profesión, nuestra intención es dar justo reconocimiento al que “sabemos que sabe”; los lectores de este humilde portal y de nuestra cuenta Twitter pueden dar fe de que siempre reconocemos al que sabe más que nosotros y es así que aprendemos y luego difundimos el conocimiento adquirido. Sigamos pues, con nuestra entrada de hoy.

…comenzó sus andanzas en el servicio militar obligatorio (“la mili”) y es allí donde le “encasquetaron” el apodo por ser tan fanático de “Star Wars”.

Ya desde el año 1996 “lidia” con Linux pero ya desde muy joven “lo que se le da” es lo de la informática. Sufrió lo mismo que Richard Stallman (y nosotros también desde los años 80): un mundo privativo donde te ofrecen “comprar, usar y desechar” * pero no preguntes cómo funciona*.

Uno de sus primeros cacharros fue ZX-Spectrum donde comenzó con el lenguaje BASIC (¿y quién no ha comenzado con ese lenguaje? ¡Ah, ahora los chavales estudian Python, menuda “paliza” para nosotros los vejetes!). Luego aprendió por su propia cuenta Pascal (¡ea, que yo tuve que pisar la universidad para poder aprender este lenguaje! 😮) , C, Prolog, y ensamblador (eax, ebx, ebp y esp fueron sus grandes amigos). Luego al entrar en el mundo GNU/Linux reafirma C, y aprende C++ y Python.

Comenzó la universidad en 1991 y su primera obra fue el Sistema Tower Pro Tarjeta CT6811 para su sueño hecho realidad: el robot Tritt (que ya vendrá algún día el “Mazinger 𝛀”, porque ya el R2D2 lo tuvo… ¡como impresora 3D, con dinastía y todo!). De 1996 al 98 se dedica en cuerpo y alma -pesetas de por medio- al campo de los micro-robots y es cuando emprende su cruzada de hacer una España con un fuerte desarrollo endógeno para librarse de la dependencia tecnológica extranjera: producir y crear todo en su tierra natal (dichas batallas aún se libran fuertemente y se ganan poco a poco con muchísimo esfuerzo, solo que ahora no está solo, sus padawan‘s lo acompañan y apoyan).

En 2003 ya hablaba de los problemas del hardware libre mediante conferencia dictada en el VI Congreso de Hispalinux y llegó a la conclusión que son los planos de hardware son los que cumplen con las 4 premisas del software libre y por ende es así que debe ser considerado el hardware libre (ahora va de que preguntéis de dónde proviene el nombre GNU y obtendréis una respuesta enrevesada parecida).

En 2007-08 trabajó sobre un mando para wii y pudo lograr que controlara su robot Skybot, demostrando con ello que las empresas privativas tienen aún mucho más campo que cubrir si tan solo se dignaran a compartir el conocimiento.

Su “grito de guerra” es:

“Más vale proyecto publicado con licencia libre, que ciento en el cajón”

Y su lema es:

Patrimonio Tecnológico de la Humanidad: es que vamos a avanzar muchísimo más como Humanidad si compartimos el conocimiento! ¡Salimos ganando todos! La riqueza se va a distribuir muchísimo más… Esto se vio desde el principio en el mundo de la ciencia. Si tú no compartes lo que has descubierto, y te lo revisan otras personas, no avanzas, ya no es ciencia lo que haces.

Patrimonio Tecnológico de la Humanidad
Patrimonio Tecnológico de la Humanidad

Tuvo una fuerte influencia el trabajo del profesor Adrian Bowyer quien lanza al mundo la primera impresora para tercera dimensión “3D” a modo de hardware libre: fue desde entonces una revolución imparable en la cual ObiJuán se especializó y contribuyó -y seguirá aportando- en su conocimiento y masificación. Hasta ahora tiene construidas 270 impresoras 3D y podéis leer su trabajo en CloneWars en este enlace.

Así mismo lleva un canal en Youtube con multitud de tutoriales donde explica y comparte con suma paciencia su conocimiento y experiencia, añadiéndole como siempre su toque personal:

ObiJuán es apasionado de la tecnología y en 2016 comezó su proyecto épico: la reconstrucción del CPU del «Apolo 11», el proyecto espacial de la NASA que llevó a nuestra humanidad a la Luna; la “paleoarquitectura” de los ordenadores, sin duda una tarea ardua. Escuchemos en palabras del propio ObiJuán el proyecto de marras:

Para él fue una bendición la tecnología que aportó Arduino en los años 90, fue como la revista “Mecánica Popular” aplicado al mundo de la electrónica. Si Arduino abrió la posibilidad de combinar los componentes y ponerlos a funcionar con los FPGAs (Field Programmable Gate Array) tendremos la posibilidad de construir nuestros propios “chips” y eso ahora mismo es lo que mantiene más ocupado a ObiJuán. Esto es así porque a pesar de todos los títulos universitarios que ha logrado, lo que le apasiona es construir y verificar por sus propios medios (vamos que la ciencia se han de replicar los mismo resultados en las mismas condiciones): es de los que crea y observa, basado en la teoría, pero la destreza manual es bien sabido que abre nuestros cerebros a nuevas conexiones sinápticas y nuevas formas y maneras de ver las cosas, ¡es de los que dicen “no me fío de lo que me dices o alegas, dejadme probar y comprobar”!

A ObiJuán no le gustan los agradecimientos; nosotros por estos lares tampoco (de hecho, debido a la dura situación de nuestro país hasta ahora es que aceptamos donaciones) pero cuando la obra es grande ES IMPOSIBLE QUE PASE DESAPERCIBIDA. Desde 1989 que comenzamos a estudiar en la Facultad de Ingeniería de la Universidad de Carabobo nuestro punto de difusión de conocimiento era el boulevard al lado del cafetín principal, AHORA LO ES EL INTERNET POR EL MUNDO ENTERO y aunque en esa época ya sabíamos que difundir el conocimiento era la clave, no es sino hasta hace poco -en serio y en firme desde el año 2014- que entramos en el mundo del saber del software libre. Pero he aquí que ObiJuán no solo usa y difunde el software libre, ¡EL HARDWARE LIBRE TAMBIÉN!  Nos aventaja por largo rato, y además se involucra en persona en causas sociales ¿Cómo no reconocer su labor? ¡Sería una injusticia!

Títulos.

Nuestro reconocimiento y agradecimiento a su labor constante y tenaz.

 

Fuentes consultadas:

En castellano:

Por medio de Twitter:


En idioma inglés:

¿Cómo funciona Mozilla Firefox? Motor Gecko y el Proyecto Quantum

Interesante es saber sobre cómo funciona el navegador web Mozilla Firefox (para nosotros, nuestro favorito) y vamos a diseccionar y explicar de manera sencilla, sin mayores pretensiones, sus diversos componentes. Para ello comenzaremos de atrás para adelante: el último Proyecto de Mozilla Firefox llamado “Quantum“, ¡Investiguemos juntos!

Introducción.

Quantum” es, como dijimos, el último proyecto que hace de Mozilla Firefox 53 una versión destacada sobre las anteriores. Tan grande es el proyecto que hubo la necesidad de ir abonando el camino para ello con el Proyecto “Electrolysis” apuntando así a un objetivo más alto. Nosotros, por estos lares, hemos seguido de cerca la evolución de los procesadores de 32 bits a 64 bits y ha sido nuestro mayor “trauma” a la hora de programar y compilar en diferentes ambientes. Pero he aquí que en los programadores de Mozilla están más bien preocupados por los dispositivos con múltiples procesadores y, de paso, en diferentes hardwares (ordenadores de mesa, dispositivos portátiles, móviles celulares y paren ustedes de contar).

Ellos primero están apostando a los procesos paralelos: cada pestaña o ventana es un hilo de programación y si colapsa solo reiniciamos el que falló, no todo el proceso principal de Firefox. Por supuesto, no solo esto lo han mejorado, nosotros por acá hemos explicado la novedosa Norma de Diseño de Cuadrícula sin contar que incluyeron temas “compactos”, nuevas extensiones para el navegador, “máscaras” de CSS, mejor experiencia con archivos multimedia, y los usuarios en Microsoft Windows pueden seleccionar si instalan la versión de 32 ó 64 bits.

Componentes principales de Gecko.

Para finalizar con la introducción diremos que muchos de los componentes del proyecto “Quantum” están desarrollados en lenguaje Rust, solo por mencionar ya que no profundizaremos en el asunto (abajo están los enlaces si queréis ir más lejos). Los componentes a la fecha son los siguientes:

  • rust-bindgen: es el “conector” entre el lenguaje C++ {con el que está(ba) escrito el código de Firefox} y el lenguaje Rust.
  • Quantum CSS ‘Stylo’: maneja las Hojas de Estilo en Cascada pero de manera “paralela”.
  • Quantum Render: se encarga de “dibujar” en pantalla.
  • Quantum DOM: se encarga de estructurar el archivo recibido en HTML.
  • Quantum Flow: para analizar el rendimiento y para mejorar la aplicación.

Más adelante explicaremos los componentes considerados básicos, mantendremos al mínimo este tutorial.

Nociones básicas.

Un navegador web es un software que lee un archivo escrito en lenguaje HTML y lo interpreta según normas recomendadas y preestablecidas para mostrarlo a nosotros de una manera interactiva. Dicho archivo reposa en un servidor web y asumiremos que simplemente es un fichero que reposa en dicho sitio -esto no es rigurosamente cierto ya que hoy en día las págnas web son dinámicas, es decir se presentan de diferentes maneras según el navegador, usuario, datos solicitados e incluso según la ubicación y dispositivo-.

Decimos que un navegador web tiene un motor web (“browser engine”) y en el caso de Firefox este motor es llamado Gecko el cual tiene muchos componentes de lo cuales nombramos algunos en la introducción.

Aclaratoria necesaria.

Todo lo que aquí presentamos es cierto para la versión Firefox 53 el cual esperamos tengáis instalado ya que hay varios elementos gráficos que solo se mostrarán correctamente en esa versión (o superior).

Simplificando al máximo.

Haciendo un panorama general, toda página web se puede dividir en tres partes principales:

Documento HTML (estructura).

Como establecimos y es un hecho cierto al nosotros ejecutar cualquier navegador web y solicitar en la barra de direcciones un dominio cualquiera lo que recibimos es simplemente un fichero con instrucciones en HTML. Un vez recibido es cuando realmente comienza el proceso de leer, analizar e interpretar dicho código. En inglés a esta pieza de software le llaman parser por su derivación del idioma latín “pars orationis” (parte del discurso, estructura gramatical) y que ellos simplemente abrevian pars, lo toman como si fuera un verbo y lo convierten en sustantivo agregandole el sufijo “er”: es así que tenemos el parser y que nosotros lo llamaremos analizador (ya la web abunda en inglés, debemos construirla también en castellano ¡ayúdanos siguiendo el ejemplo!).

Modelo de Objeto Documento («Document Object Model ‘DOM’»).

Acá es donde interviene el primer analizador: se encarga de categorizar y formar un árbol a partir de las etiquetas claves en HTML: head, body, div, footer y va más allá con cada uno de los párrafos, titulares, etiquetas personalizadas, etc. de cada sección. Lo más importante es que forma un índice de elementos a modo de catálogo para que cuando sea consultado por medio de otros componentes pueda ser retribuido rápidamente. Recordad también que debido al JavaScript dicho DOM puede ser modificado posteriormente y debe ser capaz de registrar y llevar control de dichos cambios.

Nosotros vemos al DOM como una especie de base de datos donde almacenamos el código HTML de una manera normalizada.

Hojas de Estilo en Cascada («Cascading Style Sheets ‘CSS’»).

Ahora tenemos otro analizador: el que se encarga de darle formato al código HTML que está categorizado en el DOM. En teoría cada elemento en el CSS debería tener su correspondiente en el DOM. De igual manera este analizador se encarga de categorizar de manera sucesiva los estilos que estén en el fichero -o sección- CSS. Decimos de manera sucesiva porque tal vez se nombre varias veces al mismo elemento HTML y el último en ser leído será el estilo como será presentado (esto no sucede a menudo por ser un desperdicio de trabajo redundar en el estilizado de componentes). Este último resultado es el que se va a proceder a enviar al motor de diseño.

Motor de Diseño («Layout»).

Ya con el estilo aplicado cada uno de los componentes son preparados para ser dibujados y dejarlo listo en capas para pasarlo al siguiente paso.

Motor de Capas

Recibe las capas y las lleva en orden de jerarquía según se haya determinado y las mantiene ordenadas y listas para ser presentadas al motor de dibujo.

Motor de Dibujo.

Acá se coordina todo dejando los espacios necesarios entre cada capa (que se superpone y que se puede ver y que se oculta) además de estar pendiente de las posibles modificaciones a futuro producidas por el JavaScript.

Motor “Compositor”.

Recibe y abre en procesos paralelos cada página web que visualize el usuario, ya sea en una pestaña o una ventana nueva y si esto falla por alguna razón pues entonces vuelve a abrir otro proceso solicitando de nuevo al motor de dibujo que se mantiene incólume corriendo en un proceso aparte.

Motor de JavaScript.

Acá se establecen los eventos que disparará el usuario y que podrá modificar tanto como el HTML, el CSS o ambos al mismo tiempo (la mayoría de las veces el proceso no es tan “traumático”, podría ser simplemente mostrar un texto distinto lo cual es algo más sencillo de realizar por parte del sistema operativo que por la maquinaría de Firefox en sí).

Conclusiones.

Fuentes consultadas:

En idioma inglés:

En idioma italiano:

Python logo sin texto

Python 3: llevando una bitácora de programa

En el siglo IX los chinos inventaron la brújula (aguja imantada suspendida que siempre apunta al polo norte) y desde entonces le destinaron en cada barco un habitaculum (en  latín, habitáculo en castellano) al cual los franceses le nombraron habitacle y que luego abreviaron como bitacle y que pasó a ser traducido al castellano como bitácora (a pesar de que ya teníamos la palabra traducida directamente del latín, habitáculo). Pues bien, se necesitaba llevar un registro de la posición del barco en los largos viajes por nuestro globo terráqueo (y junto al sextante para registrar los astros) todo se anotaba en un cuaderno de bitácora, o simplemente bitácora.

¿A donde nos lleva esta introducción que aparentemente no tiene nada que ver con computación? ¡Ya veremos!

Introducción.

Así como los gobiernos en tierra necesitaban conocer qué sucedió en un navío en altamar a su regreso, nosotros necesitamos saber qué sucedió en los programas que para bien desarrollemos para nuestros usuarios. Lo más básico es mostrar mensajes por pantalla a los usuarios y confiar en que ellos y ellas nos retribuyan debidamente la información… pero con muy contadas excepciones, podemos esperar sentados para no cansarnos porque eso será difícil que se haga realidad.

Es por ello que debemos guardar un registro metódico para que posteriormente podamos evaluar qué funcionó mal (por extraño que parezca, si funciona bien pues felices de la vida aunque no recibamos las felicitaciones de nuestros usuarios y usuarias de software). Otra razón de llevar un registro sería la de análisis de desempeño o incluso ejecutar un programa en modo de depuración.

La razón y la lógica indica que dichos registros que pensamos llevar deberían ser guardados en una base de datos pero en proyectos pequeños tal vez no necesitemos tal nivel de complejidad. Pongamos por caso el programa Filezilla que tiene ambas versiones tanto como servidor como cliente: por defecto no se registra mensaje alguno a menos que así lo deseemos y si decidimos guardarlo podemos especificar un archivo llevando la fecha de cada evento (opcional) e incluso podemos limitar a un tamaño específico tras lo cual al alcanzar dicho valor se procede a crear un archivo nuevo pero sin la extensión “.log” la cual es sustituida por una numeración consecutiva.

Por esta y muchas otras razones el lenguaje Python 3 tiene disponible una librería destinada para tal efecto, estudiemos pues.

Creando una aplicación modelo.

Antes de crear siquiera registro alguno debemos tener, claro está, un software al cual llevarle un registro. Para ello proponemos un programa que llamaremos calculadora1.py cuyo código es el siguiente (si queréis repasar vuestro conocimientos básicos sobre Python, revisad nuestro tutorial al respecto):

class calculadora():

  def __init__():
    print("\nCalculadora encendida.")

  def sumar( a=0, b=0):
    print("Suma a={} b={} a+b={}".format(a,b,a+b))

  def restar( a=0, b=0):
    print("Resta a={} b={} a-b={}".format(a,b,a-b))

  def multiplicar( a=0, b=0):
    print("Multiplicación a={} b={} a*b={}".format(a,b,a*b))

  def dividir( a=0, b=1):
    print("División a={} b={} a/b={}".format(a,b,a/b))

calc = calculadora
calc.sumar( 12,4)
calc.restar(12,4)
calc.multiplicar(12,4)
calc.dividir(12,4)

El código es bastante sencillo, solo las cuatro operaciones aritméticas básicas: suma, resta, multiplicación y división; reconocemos que el código es un tanto extraño pero recordad que tiene propósitos didácticos solamente. Creamos una clase con funciones que no emplean return sino que muestran por pantalla los resultados excepto en la inicialización que muestra un mensaje puramente informativo, emulando el “on” de una calculadora electrónica y anunciando el modelo virtual. Abstraigámonos entonces en el ejemplo para comenzar a modificarlo con el registro de eventos.

Agregando la utilería “logging”.

Para comenzar a utilizar la librería logging debemos incorporarla a nuestro archivo con el siguiente código:

import logging
logging.basicConfig(level=logging.DEBUG)

La primera línea enlaza la librería y la segunda línea configuramos con una constante logging.DEBUG (que tiene un valor decimal de diez), osea, el nivel (“level“) que vamos a usar: modo de depuración.

Notad todos y todas que en GNU/Linux son distintas las mayúsculas de las minúsculas, por lo tanto logging.DEBUG es una constante y logging.debug es un método, diferenciad bien esto en el siguiente código que modificamos a partir de la aplicación modelo.

import logging
logging.basicConfig(level=logging.DEBUG)

class calculadora():

  def __init__(self, nombre):
    self.nombre = nombre
    logging.debug("\nCalculadora modelo {} (encendida).".format(self.nombre))

  def sumar(self, a=0, b=0):
    logging.debug("Suma           a={} b={} a+b={}".format(a,b,a+b))

  def restar(self, a=0, b=0):
    logging.debug("Resta          a={} b={} a-b={}".format(a,b,a-b))

  def multiplicar(self, a=0, b=0):
    logging.debug("Multiplicación a={} b={} a*b={}".format(a,b,a*b))

  def dividir(self, a=0, b=1):
    logging.debug("División       a={} b={} a/b={}".format(a,b,a/b))

calc = calculadora("A1")
calc.sumar( 12,4)
calc.restar(12,4)
calc.multiplicar(12,4)
calc.dividir(12,4)

Como vemos en la siguiente imagen la salida por pantalla ha sido modificada ya que le agrega “DEBUG:root” a  todos los mensajes de resultado.

python3 calculadora2.py
python3 calculadora2.py

La primera palabra indica que estamos en modo de registro a nivel de depuración “DEBUG” y la segunda palabra indica que estamos depurando el módulo principal aunque esto no es realmente cierto. Lo mejor sería indicar desde dónde estamos imprimiendo el mensaje de depuración, en nuestro caso cualquiera de las cuatro funciones. Para ello vamos a volver a modificar el programa -que ya hemos renombrado como calculadora2.py– especificando cada función por separado:

import logging
logging.basicConfig(level=logging.DEBUG)

bita_sum = logging.getLogger("Sum")
bita_res = logging.getLogger("Res")
bita_mul = logging.getLogger("Mul")
bita_div = logging.getLogger("Div")

class calculadora():

  def __init__(self, nombre):
    self.nombre = nombre
    logging.debug("\nCalculadora modelo {} (encendida).".format(self.nombre))

  def sumar(self, a=0, b=0):
    bita_sum.debug("Suma           a={} b={} a+b={}".format(a,b,a+b))

  def restar(self, a=0, b=0):
    bita_res.debug("Resta          a={} b={} a-b={}".format(a,b,a-b))

  def multiplicar(self, a=0, b=0):
    bita_mul.debug("Multiplicación a={} b={} a*b={}".format(a,b,a*b))

  def dividir(self, a=0, b=1):
    bita_div.debug("División       a={} b={} a/b={}".format(a,b,a/b))

calc = calculadora("A1")
calc.sumar( 12,4)
calc.restar(12,4)
calc.multiplicar(12,4)
calc.dividir(12,4)

Acá vemos la salida correspondiente:

salida python3 calculadora2.py
salida python3 calculadora2.pyz

Grabando mensajes en un archivo: bitácora.log

Bien, pues ya estamos listos para comenzar a grabar en un archivo de texto plano  nuestros eventos. Esto se logra configurando de nuevo el encabezado logging.basicConfig el cual ahora lo ocuparemos en varias líneas para buscar una mayor claridad para cada uno de sus parámetros:

logging.basicConfig(
  filename="bitacora.log",
  level=logging.DEBUG,
)

Por supuesto el archivo será guardado en la misma carpeta donde se ejecuta la aplicación y para nuestra sorpresa al ejecutarla ya no muestra nada por pantalla… lo cual no es lo que realmente queremos hacer pero paciencia, primero analizemos el archivo resultante.

cat bitacora.log y combinado con el comando grep
cat bitacora.log y combinado con el comando grep

Al usar el comando cat podremos, entre otras cosas, listar el contenido de un archivo por pantalla y como probablemente la cantidad de mensajes generará gran cantidad de líneas podremos filtrar los resultados por palabra clave. ¿Recordáis que dimos nombres diferentes para la muestra de resultados a nivel de cada función? Pues con el comando grep que recibe el resultado del comando cat por medio del comando “tubería” “|” y la palabra clave “Sum” o Mul” podremos ver lo que nos interese. Ya nuestra aplicación está entrando en modo pragmático, ¡lo realmente útil para nosotros!

Agregando más pragmatismo aún: claridad al registro.

Nosotros los seres humanos en nuestro cerebro siempre buscamos darle “orden” a nuestro mundo, así está torcido lo tratamos de ver derecho y esto en el registro de eventos no ha de ser la excepción. Ya le colocamos para saber cual función produce tal registro pero le agregaremos mayor claridad en el apartado de configuración al inicio de la aplicación:

logging.basicConfig(
  filename="bitacora.log",
  level=logging.DEBUG,
  format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

Recordad siempre al final de cada línea colocar una coma para separar los parámetros, que como es multilínea tendemos a pensar que cada retorno de carro automáticamente separa cada parámeto pero no es así. En el tercer parámetro mandamos a separar con par de espacios y un guion las diferentes secciones de cada evento en cada línea:

  • Fecha y hora exacta hasta en milisegundos cuando ocurrió el evento.
  • Nombre del módulo donde se origina cada evento, en nuestro caso cada función.
  • Nivel del mensaje, clasificación (hasta ahora estamos en modo de depuración solamente DEBUG).
  • El mensaje en sí mismo.
cat bitacora.log
cat bitacora.log

Formato de tiempo mejorado.

Al formato de estampado de fecha y hora lo podremos mejorar agregando otra línea más al encabezado de configuración con una máscara que también es utlizada por el comando time.strftime():

logging.basicConfig(
  filename="bitacora.log",
  level=logging.DEBUG,
  format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
  datefmt='%d/%m/%Y %I:%M:%S %p'
)

Dejamos para vosotros os ejercitéis y veáis cómo es distinto los nuevos registros que se siguen adicionando de manera automática al final de nuestro archivo destinado a tal efecto, bitacora.log

Nivel de registro de eventos.

Como hemos repetido varias veces, del modo de depuración DEBUG no nos hemos movido hasta ahora. Por ello debemos estudiar los diferentes niveles -y constantes- que utiliza la librería logging: ya sabemos que logging.DEBUG vale diez -y se van incrementando de diez en diez- pero he aquí la tabla completa de valores:

NivelValor
numérico
FunciónUso
NOSET0no aplicano aplica
DEBUG10logging.debug()Diganóstico de problemas, muestra información bien detallada.
INFO20logging.info()Confirma que todo está funcionando correctamente.
WARNING30logging.warning()Indica que algo inesperado ha sucedido, o pudiera suceder.
ERROR40logging.error()Indica un problema más serio.
CRITICAL50logging.critical()Muestra un error muy serio, el programa tal vez no pueda continuar.

Agregando mensajes de error y su registro.

A nuestra aplicación vamos a agregarle un mensaje de error en la función de división, bien sabemos que cualquier número dividido entre cero tiende al infinito el cual es un concepto que entedemos los seres humanos pero los ordenadores no. La modificación es la siguiente (notad que b valdría uno si el valor no es pasado a la función para tratar de evitar este error):

  def dividir(self, a=0, b=1):
    if (b==0):
      bita_div.error("Alerta: el divisor debe ser distinto a cero.")
    else:
      bita_div.debug("División       a={} b={} a/b={}".format(a,b,a/b))

También modificamos el divisor en la función de división a calc.dividir(36,0) y el resultado en el registro de errores mostraría algo aprecido a esto:

Calculadora modelo A1 (encendida).
03/05/2017 11:03:07 PM - Sum - DEBUG - Suma a=36 b=3 a+b=39
03/05/2017 11:03:07 PM - Res - DEBUG - Resta a=36 b=3 a-b=33
03/05/2017 11:03:07 PM - Mul - DEBUG - Multiplicación a=36 b=3 a*b=108
03/05/2017 11:03:07 PM - Div - ERROR - Alerta: el divisor debe ser distinto a cero.

Lo próximo que haremos es modificar de manera completa nuestra aplicación con los diferentes “niveles” de mensajes.

Empleando diferentes niveles de registro.

Volvamos nuestros pasos sobre la sección logging.basicConfig donde contiene el nivel de registro de eventos para nuestra aplicación. Recordemos que la establecimos a nivel DEBUG y ahora la estableceremos a nivel INFO, guardaremos y ejecutaremos de nuevo la aplicación. Luego revisaremos el fichero bitacora.log y notaremos que no se registró el mensaje de inicialización pero si quedaron registrados los mensaje de información (y por supuesto el mensaje de error).

El siguiente paso es elevar al nivel de WARNING para obtener  solamente el mensaje de error por la división entre cero y se repite el resultado si lo elevamos a nivel ERROR. No obtenderemos mensaje alguno si lo establecemos a nivel CRITICAL ya que la divisón entre cero no solamente ha sido debidamente advertida sino que también ha sido debidamente desviada.

Pro último, y más difícil de obtener (según la aplicación de modeo didáctico que de exprofeso escogimos) es el mensaje a nivel CRITICAL. Volvemos a repetir, este comportamiento es circunstrito estrictamente a nuestra aplicación modelo: la división está en el mensaje mismo a mostrar en bita_div.CRITICAL y nunca lograremos que se muestre ya que está debidamente desviado además, si no lo desviaramos al ejecutar el compilador Python3 inmediatamente nos mostraría el error si intentamos dividir entre cero y por ende no se ejecuta el programa.

Nosotros somos de experimentar al máximo, nos hacemos muchas, muchísimas preguntas: ¿Y si compilamos la aplicación, es decir la convertimos a lenguaje binario para ejecutar y lograr el mensaje a nivel CRITICAL?

Para ello -brevemente- podemos instalar PyInstaller:

sudo pip3 pyinstaller

Luego simplemente vamos a la carpeta con nuestro fichero calculadora2.py (habiendo eliminado la desviación del error de división entre cero):

pyinstaller calculadora2.py

Y luego de cierto tiempo (¡oh, sorpresa, también utiliza logging para mostrar el progreso de la compilación pero con unos códigos no recomendables de niveles de registro -valores personalizados-) y en una carpeta dist encontraremos nuestro ejecutable listo para ser experimentado. Nosotros obtuvimos esto, si queréis practicad que algo parecido obtendréis:

pyinstaller calculadora.py
pyinstaller calculadora.py

Entonces estaremos listo para ejecutar nuestro flamante binario, nos vamos con el explorador de ficheros Nautilus de Ubuntu a la carpeta dist le damos click derecho, ejecutar y ¡oh, sorpresa! el fichero bitacora.log se genera y aparece… pero con cero bytes, sin nada dentro, ¿qué ha sucedido aquí?

bitacora.log vacio cero bytes
bitacora.log vacio cero bytes

Pues que simplemente la librería de registro abre el archivo bitacora.log (crea el archivo) pero la división entre cero no le permite llegar a ejecutar el grabado del mensaje, ya que las instrucciones son anidadas y primero trata de dividir y luego mostrar el mensaje, pero como se “cuelga” pues no registra nada de nada.

En este punto ya es bueno concluir algo muy cierto: el registro de errores incluso nos beneficiará al obligarnos a pensar dónde colocar los mensajes necesarios para futuras mejoras y en el caso del software libre donde TODOS podemos ser parte de un equipo de programadores esta ayuda es tremendamente bienvenida.

Otra pregunta que nos hacemos, ¿qué sucede si no establecemos un nivel de registro específico en logging.basicConfig? De manera predeterminada la utilería está en nivel WARNING y los mensajes que sean iguales o superiores a este nivel serán registrados (WARNING, ERROR  y CRITICAL). No obstante vamos a dar un paso más allá en nuestros estudios y vamos a configurar para que sean nuestros propios usuarios quienes establezcan un nivel de registro lo cual consideramos útil para ellos que NO son programadores y que tal vez necesiten cierta orientación sin necesidad que ellos y/o ellas lleguen a tener que descargar el código fuente de la aplicación -que siempre estará al alcance por ser software libre-.

Que los usuarios y usuarias establezcan su nivel de registro.

Pasando parámetros a una aplicación desde la línea de comando.

En el mundo de Python hay varias librerías que nos permiten “pasar” parámetros hacia “lo interno” de nuestras aplicaciones, algunas de ellas son -pero no son todas-:

  • getopt es una librería la cual se deriva de una del lenguaje C llamada, claro, getopt().
  • optparse escrita para Python pero que actualemente está “descontinuada”.
  • argparse la cual curiosamente deriva de optaprse pero ofrece total compatibilidad a la versión 3 -y a futuro-.

Por esa razón escogemos esta última para evitarnos dolores de cabeza a futuro.

argparse.

Introducción a argparse.

Debemos hacer una breve introducción al concepto de parámetros tanto opcionales como obligatorios. De manera general las aplicaciones corren sin ninguna isntrucción especial: escribimos el nombre del fichero, el sistema operativo revisa si es un ejecutable, o carga en memoria y ejecuta las instrucciones contenidas.

Un ejemplo sencillo es el comando para listar ficheros y directorios en una ventana terminal: ls. Sin más dicho comando nos muestra por pantalla los ficheros y directorios contenidos en la carpeta desde donde la ejecutamos. Si hubiera alguna carpeta y queremos saber su contenido debemos escribir ls nombre-de-la-carpeta y allí tenemos un parámetro opcional que le estamos pasando a la aplicación: le estamos ordenando listar el contenido de un directorio. Decimos que es opcional porque, como vimos, el comando no necesita nada para funcionar pero somos nosotros los que tenemos la necesidad de pedirle algo muy específico. Pero adicionalmente a la petición específica queremos que nos lo muestre de una manera específica y para poder diferenciar los nombres de las carpetas -o archivos- que pidamos de la forma como la va a presentar pues nació la idea de colocar palabras claves para diferenciar (recalcamos que estamos con el comando ls como ejemplo útil ya que es un comando extremadamente básico). Así podemos teclear ls nombre-de-carpeta -l para listar en modo columna o el también llmado modo largo (nombres de ficheros o directorios uno encima del otro con detalles de tamaños, fecha, atributos, etc.).

Es por esta razón que se estableció ciertas normas para pasar parámetros, en general podemos decir que:

  1. Se utiliza un guion “-” como prefijo para indicar un parámetro y se acompaña generalmente con una sola letra que más que suficiente porque tenemos 54 opciones distintas (27 caracteres mayúsculas y minúsculas).
  2. Como estrategia nemotécnica se utilizan dos guiones juntos “–” junto con palabras o incluso frases para que sea de manera explícita su recordación.
  3. También se da el caso que a las dos opciones anteriores se le agregue sin dejar espacios un signo de igualdad y a continuación algún valor condicionante (que puede ser imprescindible o no).
  4. Como para algunos el punto anterior no les parece elegante, también se estila colocar un espacio y a continuación algún valor condicionante.

Siguiendo con el ejemplo del comando ls:

Ejemplo del punto 1: comando “ls -r” (lista los archivos y carpetas en orden alfabético inverso, de la letra zeta hacia la letra a).

Ejemplo del punto 2: comando “ls –reverse” ídem al punto anterior pero más fácil de recordar y explícito para mostrar.

Ejemplo del punto 3: comando “ls –sort” ordena las lista de ficheros por orden de tamaño, del más grande hacia el más pequeño, pero sucede que hay muchas maneras de ordenar ese listado y si lo ejecutamos así sin más nos solicita un parámetro necesario. Podemos pedirlo por tamaño así que escribimos “ls –sort=size” y veremos el resultado con primero los más grandes yendo luego progresivamente hasta los más pequeños. Por cierto, este comando “largo” tiene un equivalente “corto”: ls -s.

Ejemplo del punto 4: comando “ls patron-a-buscarcomo por ejemplo si queremos ver solamente los archivos que comienzen con la letra “a”: “ls a*“.

Primeros pasos con argparse.

Para comenzar a utilizar argparse en nuestro programa, simplemente hagamos un fichero nuevo y le colocamos los siguiente:

import argparse
analizador = argparse.ArgumentParser(description="Programa demostrativo de argparse")
analizador.parse_args()

Al salir lo nombramos como mi_programa.py y lo ejecutamos con python3 mi_programa.py y, por supuesto, no hace nada de nada ya que no le escribimos ningún código adicional. Pero ahora vamos a ejectuarlo acompañado de un parámetro como lo es el siguiente: python3 mi_programa.py -h y obtendremos la siguiente salida:

usage: mi_programa.py [-h]

Programa demostrativo de argparse.

optional arguments:
 -h, --help show this help message and exit

Como vemos todo viene preconfigurado para utilizar el idioma inglés por defecto, pero pronto podremos darle un uso mejor para orientarlo hacia el idioma castellano en un tutorial dedicado al tema. Notad que especifica que el “parámetro largo” para ayuda es –help. Adicionalmente, cualquier otro parámetro que le pasemos manifestará desconocerlo -no hemos programado nada áun, por ahora-. Por lo pronto ya cumplimos con iniciar el uso práctico de argparser, continuemos aprendiendo.

Agregando otro argumento opcional.

Como vemos argparse tiene al menos un argumento establecido por defecto, el de ayuda [el cual es opcional, está mostrado entre corchetes], y ahora nosotros vamos a agregarle nuestro propio argumento para establecer el nivel de registro de eventos. Para ello especificaremos la palabra clave -log_lev acompañado del nivel que deseemos establecer, a continuación lo pasamos por una serie de tamices con la instrucción condicional if~elif~else y si coincide mostramos por pantalla la opción elegida:

import argparse
analizador = argparse.ArgumentParser("Programa demostrativo de argparse")
analizador.add_argument("-log_lev", help="Utilice DEBUG, INFO, WARNING, ERROR o$
analizador.parse_args()
argumentos = analizador.parse_args()
if argumentos.log_lev == 'DEBUG':
 print("DEBUG")
elif argumentos.log_lev == 'INFO':
 print("INFO")
elif argumentos.log_lev == 'WARNING':
 print("WARNING")
elif argumentos.log_lev == 'ERROR':
 print("ERROR")
elif argumentos.log_lev == 'CRITICAL':
 print("CRITICAL")
else:
 print("Opcion no válida de nivel de registro de eventos.")

Como vemos esto simplemente es el armazón para el manejo del pase de parámetros a nuestro programa didáctico para el registro de eventos con la utilería logging.

En este punto corred vuestro programa varias veces, experimentad con el pase de parámetros para que luego continuemos con el último paso de este tutorial: la fusión de logging con argparse.

Uniendo “logging” con “argparse”.

Ya para finalizar unimos el código de ambos ejemplos y la idea es la siguiente: al utilizarse sin parámetros se establece el nivel de registro en WARNING que es el nivel predeterminado. Si se utiliza el parámetro -log_lev sin acompañarlo de valor alguno, la librería argparse se encargará debidamente de orientar al usuario sobre las opciones disponibles. Si el usuario usa alguna opción disponible válido pues se establece debidamente el nivel de registro correspondiente.

Queda para vuestra práctica el permitir que los usuarios especifiquen un nombre de archivo para el registro de eventos.

Acá tenemos el código final, espero os haya servido para aprender algo nuevo sobre el lenguaje Python.

import logging
import argparse

analizador = argparse.ArgumentParser("Programa demostrativo de argparse")
analizador.add_argument("-log_lev", help="Utilice DEBUG, INFO, WARNING, ERROR o CRITICAL")
analizador.parse_args()
argumentos = analizador.parse_args()
if argumentos.log_lev == 'DEBUG':
 logging.basicConfig(level=logging.DEBUG)
elif argumentos.log_lev == 'INFO':
 logging.basicConfig(level=logging.INFO)
elif argumentos.log_lev == 'WARNING':
 logging.basicConfig(level=logging.WARNING)
elif argumentos.log_lev == 'ERROR':
 logging.basicConfig(level=logging.ERROR)
elif argumentos.log_lev == 'CRITICAL':
 logging.basicConfig(level=logging.CRITICAL)
else:
 logging.basicConfig(level=logging.WARNING)
# Opción no válida, se establece nivel WARNING por defecto.


logging.basicConfig(
 filename="bitacora.log",
 format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
 datefmt='%d/%m/%Y %I:%M:%S %p'
)

bita_sum = logging.getLogger("Sum")
bita_res = logging.getLogger("Res")
bita_mul = logging.getLogger("Mul")
bita_div = logging.getLogger("Div")

class calculadora():

def __init__(self, nombre):
 self.nombre = nombre
 logging.debug("\nCalculadora modelo {} (encendida).".format(self.nombre))

def sumar(self, a=0, b=0):
 bita_sum.info("Suma a={} b={} a+b={}".format(a,b,a+b))

def restar(self, a=0, b=0):
 bita_res.info("Resta a={} b={} a-b={}".format(a,b,a-b))

def multiplicar(self, a=0, b=0):
 bita_mul.info("Multiplicación a={} b={} a*b={}".format(a,b,a*b))

def dividir(self, a=0, b=1):
 if (b==0):
 bita_div.error("Alerta: el divisor debe ser distinto a cero.")
 else:
 bita_div.info("División a={} b={} a/b={}".format(a,b,a/b))

calc = calculadora("A1")
calc.sumar( 45,5)
calc.restar(45,5)
calc.multiplicar(45,5)
calc.dividir(45,0)

Fuentes consultadas:

En idioma inglés:

ABC HunSpell

Hunspell tutorial

Repetimos que esta página no va de ciencias sociales, sin embargo somos fanáticos de la ortografía y en esta oportunidad os presentamos una herramienta para corregir nuestros escritos, que ya son bastantes, por demás. Ahora es el punto donde nos diréis “ea, tío,  ¿de qué váis si eso está integrado en ‘todos’ los programas?” Pues bueno preparaos a sorprenderos con los que os vamos a contar, ¡vamos a aprender a programar para corregir nuestra ortografía!

Introducción.

Ya tocamos el tema del idioma inglés anteriormente, su semántica y ortografía, un toque leve pues, nada profundo. Ahora os presentamos una herramienta llamada HunSpell para ayudarnos rápidamente a corregir archivos completos de una manera automatizada con dos grandes ventajas: se puede usar la línea de comandos (scripts bash) y con Python3.

Historia.

HunSpell deriva de MySpell.

MySpell.

MySpell fue desarrollado por Kevin Hendricks quien buscaba integrar varias herramientas de software libre para la suite de oficina Apache OpenOffice.org pero no fue sino con la ayuda de Kevin Atkinson (creador de Aspell -sucesor de Ispell- y Pspell) y un arduo trabajo en C++ que nace MySpell el cual soporta “Affix compression” el cual tiene una capital importancia para nosotros los programadores y ya veremos cómo cuando toquemos el tema con Python (Python3 en específico).

HunSpell.

¿Por qué crean HunSpell si ya existía MySpell? Porque este mundo es grande y ancho y para el idioma húngaro se necesitaba un corrector ortográfico que pudiera manejar UTF-8 y por ende los idiomas del mundo entero. Nosotros por estos lares siempre indicamos -y luchamos- para que esta codificación en bases de datos, lenguajes de programación y lenguajes de marcado sean presentados correctamente tanto por pantalla como por impresoras (aunque estas útlimas se están dejando de usar para ahorrar papel, tinta, dinero y recursos naturales). De allí proviene el “HUN-“del idioma húngaro, “Spell” es deletrear en inglés, de allí la palabra compuesta.

La última versión estable data del 2011 y al igual que su predecesor MySpell, HunSpell está escrito en lenguaje C++. En su repositorio bien reza “la librería de corrección ortográfica más popular” y al momento de escribir estas líneas tenía 7 horas de haber sido actualizado dicho repositorio ¡está más viva que nunca HunSpell!

Programas que utilizan HunSpell.

Y he aquí la sorpresa: HunSpell es el corrector ortográfico de fuente abierta para una gran cantidad de programas que usamos diariamente, por nombrar unos cuantos:

  • Apache OpenOfiice.
  • ¡LibreOffice!
  • Thunderbid.
  • Mozilla Firefox ¡desde el año 2005!
  • Google Chrome.
  • Google Chromium.
  • SeaMonkey.
  • WinShell.
  • Opera.

Lenguajes de programación y HunSpell.

Ya os dijimos que HunSpell está escrito en lenguaje C++ pero al menos hay dos lenguajes en los cuales podemos imprtar estas librerías. Uno es Python, en el cual estamos vivamente interesado gracias a su gran versatilidad y plataformas que lo soportan. El otro es el lenguaje R que ha tomado auge recientemente y que, por ahora, no tocaremos su uso. En nuestra sección de fuentes consultadas en idioma inglés os dejamos unos enlaces con ejemplos que nos parecieron bastantes sencillo por si queréis ahondar en ese tema.

Instalando HunSpell en Ubuntu.

Como en las distribuciones basadas en Debian, podemos utilizar apt para instalar por una ventana de comandos desde nuestros repositorios predeterminados. Para ello con una simple línea -con derechos de administrador root-, escribimos lo siguiente:

sudo apt-get install hunspell
apt get install hunspell
apt get install hunspell

Previo a este comando es recomendable usar apt-get update para sincronizar el catálogo de aplicaciones entre nuestro ordenador y los repositorios que tengamos predefinidos. Una vez hayamos instalado podemos consultar la versión que hayamos instalada:

hunspell -v
hunspell -v
hunspell -v

Como podéis constatar aparecen las atribuciones debidas hacia Ispell, László Németh, MySpell, Kevin Hendricks y openOffice.org: así es el software libre, se debe heredar la licencia y hacer econocimiento expreso a los autores a fin de evitar el patentado y que devenga en software  privativo.

Uso por línea de comandos de HunSpell.

ABC HunSpell
ABC HunSpell

Uso de Hunspell de manera interactiva.

Una vez tengamos instalado HunSpell podemos, sin más, abrir una ventana de comando y comenzar a usarlo. Aunque su uso principal es para revisar archivos o ficheros de texto, también podemos hacerlo interactivamente. Primero debemos conocer dónde estamos parados, conocer cuáles diccionarios tenemos instalados, y por ello usaremos el siguiente comando -el cual devuelve una extensa respuesta-:

hunspell -D

Este parámetro nos devolverá, esencialmente, tres secciones:

  1. Rutas de búsqueda: dependiendo de la cantidad de programas que tengamos instalados, cada uno de ellos -si utilizan MySpell o HunSpell- tienen sus propios diccionarios. Dada la filosofía del software libre, tenemos la opción de usarlos, descargar otros e incluso crear nuestros propios diccionarios -¡avanzado!-.
  2. Diccionarios disponibles: la “segunda” ubicación es la del propio HunSpell, generalmente está ubicada en la carpeta “/usr/share/hunspell” (esta ruta puede variar según vuestra distribución linux utilizada). En estas rutas también puede aparecer la ruta “/usr/share/myspell” así que si tenemos más opciones, pues mejor. Los diccionarios allí listados son simples ficheros cuyo nombre está compuesta por dos letras minúsculas, el guión bajo “_” y dos letras mayúsculas. Las primeras dos letras corresponden al idioma y las segundas dos letras corresponden a la distribución regional. Por ejemplo “en_GB” representa “english Great Britain”, “fr_FR” francés de Francia, “fr_CA” francés de Canadá y así sucesivamente. Para nuestro país -aunque lo identifican mal- nos corresponde “es_VE” osea español de Venezuela (cuando en realidad hablamos es castellano). Importante destacar que si queremos cargar cualquiera de los diccionarios en esta sección listada no es necesaria especificar su ruta ya que HunSpell sabe muy bien donde están ubicados.
  3. Diccionario cargado: dependiendo de la configuración regional que tengamos en nuestro sistema operativo, será cargado un diccionario de manera predeterminada, por lo cual, como dijimos, podemos usar sin más a HunSpell. Para nuestro caso tenemos el fichero “es_VE.dic” y su contraparte -ya veremos su uso- “es_VE.aff“.

Vamos, pues, a comenzar a usar a HunSpell. Ya sabemos cual diccionario tenemos cargado por defecto, pero acostumbremonos a penar internacionalmente, que es de cultura general saber o al menos tener nociones de varios idiomas modernos:

hunspell -d es_VE

Acá notamos que usamos el parámetro “-d” para cargar un diccionario que se encuentra en la ruta de HunSpell, por lo que no es necesario especificar su ubicación, HunSpell sabe ya donde está. A continucación presionamos intro o enter y escribimos la plabra que deseamos revisar y presionamos INTRO. Si la palabra está bien escrita (HunSpell la busca en el diccionario y consigue una conicidencia exacta) nos devolverá ya sea asterisco “*“, signo de suma “+” o un signo de resta ““. Por ahora nos conformamos en saber que la palabra es correcta. De estar mal escrita la palabra (no se consigue en el diccionario) HunSpell nos devuelve una lista de palabras aproximadas donde, generalmente, la primera que aparece es la correcta. Aquí es muy importante el archivo “es_VE.aff”, que utiliza el “affix compression” -fijaos la extensión del fichero-: hay palabras raíces y con prefijos, sufijos o ambos, encontramos su aproximación a la palabra correcta. Es decir, según unas reglas predeterminadas (palabras raíces, palabras derivadas) podemos corregir y lograr la ortografía.

Muchas veces devolverá pocas y a veces varias, veamos la imagen siguiente:

hunspell -d es_VE
hunspell -d es_VE

Notamos que si escribimos mal el nombre de nuestro país, HunSpell nos devuelve en primer lugar la aproximación más cercana y luego una segunda palabra que medio se le parece. Hasta aquí todo bien pero si escribimos la palabra “vurro” (sic) lo primero que nos devolverá es “curro” -palabra no muy común en Venezuela- y en segunda opción la buscada, el animal muy útil en las granjas aún hoy en día. Luego nos muestra palabras menos comunes aún. Es por ello que debemos aprender a crear o modificar nuestros propios diccionarios de acuerdo al uso más común que damos a nuestra habla cotidiana. Es evidente que este diccionario proviene de España ¡NO HAY PROBLEMA CON ESO! Allá se originó nuestro castellano, de la región abundante en castillos, Castilla, que era más fortificada y pudo someter militarmente al resto de la península ibérica e inclusó expulsó a los moros que por 600 años estuvieron allí construyendo ciudades y civilizando a la población con los últimos avances científicos de la época.

Pero seamos sinceros, las diferencias son evidentes entre el castellano de España y el castellano de Venezuela:

  • coche -> carro.
  • móvil -> celular (teléfono).
  • piso -> apartamento (departamento, vivienda).
  • ordenador -> computadora.
  • contadores -> medidores (electricidad).
  • Y paren ustedes de contar…

Uso de Hunspell sobre archivos de texto.

Cuando le indicamos a Hunspell que trabaje sobre un archivo de texto no es completamente automático su comportamiento, en cierto modo es interactivo con nosotros. Pero primero veamos el comando a utilizar:

hunspell -d es_VE archivo_de_texto.txt

Una vez comenzamos la tarea, Hunspell cambia sin preguntar las palabras mal escritas que encuentre en coincidencia en el diccionario especificado. Pero si no consigue una coincidencia clara nos pregunta a nosotros con las siguientes opciones:

  • Tecla “R”: reemplaza la palabra mal escrita completamente.
  • Tecla “Espacio”: Acepta la palabra solamente por esta vez.
  • Tecla “A”: Acepta la palabra para el resto de esta sesión.
  • Tecla “I”: Acepta la palabra, y el ingreso en su diccionario privado.
  • Tecla “U”: Acepta y añade la versión minúscula en el diccionario privado.
  • Tecla “S”: Pedir una raíz y una palabra modelo para almacenarlas en el diccionario personal.
  • Números: cuando son pocas las opciones uno puede pulsar un solo número pero a veces la lista es extensa y hay que pulsar dos, como por ejemplo doble cero.
Hunspell sobre un archivo de texto
Hunspell sobre un archivo de texto

Uso práctico de Hunspell.

Pues si ya ustedes son lectores habituales de este vuestro humilde blog -y sino pues ahora lo sabrán- somos terriblemente pragmáticos con el software, nos gusta, amamos y nos encanta darle uso práctico a las herramientas informáticas. Para este caso estamos usando el Hunspell con los archivos de texto generados con el reconocimiento óptico de caracteres, al cual le dedicamos una entrada correspondiente. A esas imágenes que capturamos con un aumento de 200% (zoom le dicen las personas que hablan inglés) y con ayuda de el maravilloso Shutter capturamos por párrafos y luego los corregimos de manera rápida con Hunspell.

Fuentes consultadas.

En idioma castellano.

En idioma inglés.

Etherpad Foundation Logo

Etherpad editor texto colaborativo en línea

Comenzamos el 2017 con un breve tutorial sobre Etherpad, específicamente la versión ligera o Etherpad Lite, la cual es un editor de texto colaborativo en línea sin mayores pretensiones de seguridad y/o registro pero sencilla y poderosa en concepto. Veremos como instalarla, utilizarla y hasta revisaremos de forma sencilla cómo funciona, acompañenos por favor 😎 .

Introducción.

Mucho se habla de las “nubes” en forma metafórica y siempre hemos sido un tanto excépticos al uso -y abuso- de dicho término. Somos sobre todo pragmáticos pero también cautelosos en cuanto a la tecnología que almacena nuestros datos en internet y “prometen el oro y el moro” a diestra y siniestra pero he aquí que nos llamó poderosamente la atención la herramienta Etherpad por su aparente sencillez -luego veremos muy bien los detalles “de debajo del capó“-.

En los últimos tiempos hemos visto el surgimiento de aplicaciones en línea (documentos de texto, hojas de cálculo y hasta edición de imágenes) que por una tarifa mensual alquilamos el almacenamiento de los ficheros –de algo tenemos que vivir los programadores, comemos y tenemos familias que mantener- pero tal vez no necesitemos de una herramienta tan sofisticada para nuestros propósitos. He aquí que interviene Etherpad: podremos tener “listas por hacer”, documentos, declaraciones, ENTREVISTAS en línea con resaltado sobre lo que escribe cada participante identificado con diferentes colores y podremos embutirlo en cualquiera de nuestras aplicaciones con tan solo incluir una ventana al navegador web que gustéis (lo probamos con Mozilla Firefox y Chromium). Esencialmente eso es lo que hace Etherpad, después que lo instalemos ampliaremos en mayores detalles, no muchos debido a la aparente simplicidad de la aplicación.

La historia de Etherpad está bien resumida en el siguiente párrafo: la aplicación fue lanzada el 19 de noviembre de 2008 por David Greenspan, Aaron IBA y J. D. Zamfirescu (los dos últimos solía trabajar para Google). Más tarde se les unieron -los también empleados por Google- Daniel Clemens y el diseñador David Cole. El sitio original fue llamado etherpad.com (hoy en día el enlace redirige hacia etherpad.org). El 4 de diciembre de 2009 Google compró AppJet, la compañía que posee el software y se anuncia que esta solicitud de colaboración estará disponible bajo licencia Open Source. El 17 de diciembre de 2009, Google libera los código fuentes de Etherpad bajo licencia Apache v2.

En esta entrada evaluaremos la versión Etherpad 1.6.1 disponible tanto para GNU/Linux como para sistemas operativos privativos. Para compartir vía Torrent la versión disponible es la 1.4.1.

Etherpad Lite fue reescrita completamente en un servidor JavaScript utilizando Node.js y del lado del cliente también utiliza javaSript en un 99%.

Los mismos programadores, que antes trabajaron para Google, destacan por Twitter la versatilidad de Etherpad y se erigen como competencia directa al servicio “Google Docs”:

 

La última versión también está alojada en GitHub.com y está amparada por la licencia Apache 2.

etherpad lite animated.gif
etherpad lite animated.gif

Ambiente de trabajo.

Nosotros utilizamos un ordenador con Ubuntu 16.04 en una red de área local que configuramos por DHCP que nos otorga la siguiente dirección IPv4 fija: 192.168.1.47, aparte de tener derechos de administrador “root” eso es todo lo que necesitamos, ¿sencillo, cierto?

Proceso de instalación.

Abrimos una ventana terminal e introducimos el siguiente comando:

sudo apt install git curl python libssl-dev pkg-config build-essential

Cada una de las palabras a la derecha de “apt install” respresenta un sfotware en particular que no describiremos detalladamente pero por acá hemos escrito sobre Git y Python, por si acaso queréis ampliar vuestros conocimientos pero para el caso que nos ocupa no es necesario saber usarlos -pero al menos tener noción de que existen-.

sudo apt install git curl python libssl-dev pkg-config build-essential
sudo apt install git curl python libssl-dev pkg-config build-essential

Como véis nosotros ya teníamos instalado lo necesario debido a nuestro trabajo de programación en otros asuntos (esto es lo que denominamos entorno de trabajo, se comparten muchos elementos, cuidad de poner muchos proyectos en una sola computadora por razones de estabilidad y uso de versiones compartidas).

Ahora procederemos a instalar Node.js 6.9.2 con la siguiente orden:

wget https://nodejs.org/dist/v6.9.2/node-v6.9.2-linux-x64.tar.xz
wget node-v6.9.2
wget node-v6.9.2

Una vez descargado con wget los archivos comprimidos procedemos a extraerlos con el comando tar en la carpeta donde lo descargamos:

tar xJf node-v6.9.2-linux-x64.tar.xz

Luego creamos un directorio y movemos los archivos pero con derechos de administrador “root”:

sudo mkdir /opt/nodejs/ && sudo mv node-v6.9.2-linux-x64/* /opt/nodejs
sudo mkdir nodejs and sudo mv
sudo mkdir nodejs and sudo mv

En la imagen anterior, por error, no usamos la orden “sudo mv” y eso ocasionó los mensajes de “no se pude mover” es por ello que casi no usamos el concatenador “&&“, generalmente ejecutamos paso por paso, pero bueno, errar es de humanos y reconocemos nuestro fallo, a la final completamos el proceso en una segunda línea.

Tras la pequeña falla subsanada, agregamos los enlaces simbólicos hacia nuestro perfil de usuario en el ordenador:

echo "PATH=$PATH:/opt/nodejs/bin" >> ~/.profile

Si todo sale bien pues felicitaciones, tenemos instalado Node.js en nuestra máquina de pruebas.

Instalando el código fuente de Etherpad.

En idioma inglés a esto lo llaman “instalar los (archivos) binarios”, nosotros simplistas siempre pues lo llamamos código fuente o más simple aún: fuente de Etherpad. Para ello haremos lo siguiente:

  1. Crearemos un directorio llamado etherpad en la carpeta opt.
  2. Cambiaremos el propietario de la carpeta con chown hacia nuestro nombre de usuario whoami aprovechando las cualidades del bash y el uso de variables de paso entre comandos.
  3. Cambiamos al directorio creado ya sin credenciales de administrador “root” porque la carpeta nos pertence ahora.
  4. utilizamos el comando git para descargar el código fuente de Etherpad.
sudo mkdir /opt/etherpad
sudo chown -R $(whoami).$(whoami) /opt/etherpad
cd /opt/etherpad
git clone git://github.com/ether/etherpad-lite.git
Clonando el repositorio de Etherpad
Clonando el repositorio de Etherpad

Ejecutando por primera vez Etherpad.

Para comenzar a usar Etherpad (“levantar el servidor”) pues ejjecutamos un archivo de procesos por lote o bash llamado “run.js” desde donde se verifican las variables de entorno (esencialmente nos prohíbe ejecutarlo con derechos de administrador “root” recordad que es un servicio web expuesto a la internet y a todo el mundo) y allana el camino para ejecutar a su vez a otro bash, installDeps.sh, que hace las siguientes comprobaciones:

  1. Se asegura que NO se haya llamado desde el directorio bin (en nuestro ordenador de ejemplo nos quedó instalado en la siguiente vía: “/opt/etherpad/etherpad-lite”).
  2. Comenzamos a usar el comando hash que devuelve cero si encuentra la vía donde están instaladas las respectivas aplicaciones (¿recuerdan lo que comentamos sobre agregar enlaces simbólico a la vía PATH al fichero /.profile)
  3. En el caso que estemos ejecutando sobre SunOS necesitaremos instalar el comando ggrep -no se aplica a nuestro ordenador con Ubuntu-.
  4. Verifica que tengamos instalado curl el cual usaremos para descargar lo que necesitemos de la internet.
  5. Verifica si tenemos node.js instalado.
  6. Verifica si tenemos npm instalado -y su versión-. Npm nos permite manejar cientos de miles de aplicaciones escritas para JavaScript.
  7. Verifica la versión de node.js instalada (0.10.x o superior).
  8. Confirma el nombre del archivo “settings.json” (pronto lo abriremos y editaremos).
  9. De no conseguir “settings.json” pues copia una plantilla por defecto para poder comenzar a trabajar.
  10. De nuevo tomamos a npm y le indicamos que actualize o instale toda nuestra “paquetería” (este comando puede tomar algo de tiempo dependiendo de vuestra máquina y vuestra velocidad de conexión al internet).
  11. Verificamos que la versión jQuery que tengamos sea mínimo 1.9.1 de no ser así utilizamos curl para descargarla.
  12. Importante: en la carpeta “/var” donde tengamos instalado Etherpad (para nuestro ejemplo en “/opt/etherpad/etherpad-lite/var”) reposan los archivos que comienzan con la palabra “minified” que esencialmente contienen los guiones JavaScript que corren del lado del cliente. SUPONEMOS que son borrados y creados de nuevo cada vez que se ejecuta Etherpad porque se trata de reunir todas las piezas y entregarlas al cliente para que se ejecuten allá. Cada archivo contiene una licencia de uso Apache 2 e imploran ayudar a comentar -y ayudar- a mantener el código. Esta parte garantiza que cada que vez que “reiniciemos” a Etherpad sean instaladas y “compiladas” las intrucciones al cleinte con las nuevas versiones. También en esta carpeta reposa la base de datos “dirty.db” -manejada con SQLite- la cual es para propósitos de desarrollo y pruebas (lo que enseñamos nosotros en esta vuestra página web) pero que para entornos “de producción” recomiendan sustituir con mySQL.
  13. Se asegura que tenga los guiones .js y .css “limpiecitos” antes de comenzar a ejecutar.

Nos tomamos el “atrevimiento” de copiar el archivo installDeps.sh tal cual se muestra al día sábado 07 de enero de 2017 y le colocamos, como valor agregado, instrucciones al usuario en idioma castellano. Si vosotros queréis contribuir al código fuente central cread una cuenta en GitHub y haced una divergencia de código “fork” en vuestra cuenta, programáis y modificaís y hasta quien sabe, a futuro podéis proponer cambios a los programadores originales para que lo incorporen a la rama oficial. Pero por ahora nosotros lo que queremos es enseñaros unos pocos archivos y no vale la pena copiar todo el código, por eso GitHub tiene una sección llamada Gist (tiza) para estos casos menores y rápidos, especial para ejemplos pequeños, mirad como queda nuestro trabajo:

Ahora si que se ejecuta el guión server.js el cual es el que consideramos “compila” y “levanta” el servidor pero mejor os colocamos la cabezera del archivo para que tengaáis una noción al respecto:

#!/usr/bin/env node
/**
 * This module is started with bin/run.sh. It sets up a Express HTTP and a Socket.IO Server. 
 * Static file Requests are answered directly from this module, Socket.IO messages are passed 
 * to MessageHandler and minfied requests are passed to minified.
 */

/*
 * 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
etherpad-lite bin run.sh (1)
etherpad-lite bin run.sh (1)
etherpad-lite bin run.sh (2)
etherpad-lite bin run.sh (2)

Como vemos, debe ser llamado desde run.sh quien a su vez -ya explicamos- actualiza y borra datos anteriores con installDeps.sh y ejecuta el servicio en sí. Ahora tomad un cafecito y volvéis para mostraros cómo funciona del lado del cliente, con lo que nos toparemos todos los días.


Ejecutando del lado del cliente.

Nuestro servidor de pruebas está ubicado en la dirección IPv4 fija en nuestra red de área local con los números 192.168.1.47 y nos conectaremos con el puerto 9001 el cual es por defecto (de hecho ya tenemos un servidor web Apache2 escuchando en los puertos 80 y 443). Veremos lo siguiente:

Usando Etherpad-lite en servidor local (1)
Usando Etherpad-lite en servidor local (1)

Por otra parte nos fijamos en la ventana terminal desde donde lanzamos Etherpad y observamos cierta actividad.

Usando Etherpad-lite en servidor local (2)
Usando Etherpad-lite en servidor local (2)

En esta última imagen apreciamos la versión que tenemos instalada y la advertencia que no tenemos configurados al usuario “admin” y su contraseña (más adelante lo modificaremos) y también vemos que se ha creado un archivo llamado “prueba” con un nombre aleatorio y la dirección IP del navegador que tenemos conectado.

Esto es lo que veremos, un mensaje de bienvenida, en inglés (ya vamos a cambiar la configuración) y podemos desde ya el comenzar a escribir lo que necesitemos o queramos.

Usando Etherpad-lite en servidor local (3)
Usando Etherpad-lite en servidor local (3)

Desde otra computadora ubicada en la misma red de área lcoal nos conectamos y de una vez en el registro o bitácora nos mostrará a cual archivo se conectó y su dirección IP así como la dirección IP.

Usando Etherpad-lite en servidor local (4)
Usando Etherpad-lite en servidor local (4)

En ambas computadoras procedemos a identificarnos para que podamos visualizar en diferentes colores lo escrito por cada uno de los participantes.

Usando Etherpad-lite en servidor local (5)
Usando Etherpad-lite en servidor local (5)

Abajo a la derecha (esquina inferior derecha) hallaremos el ícono para iniciar una conversación aparte del codumento que estemos editando. No consideramos explicar mayor cosa porque sabemos que los usuarios son expertos en esto de los “chats” 😉

Usando Etherpad-lite en servidor local (6)
Usando Etherpad-lite en servidor local (6)

Si hacemos click en la esquina superior derecha, en el ícono de una rueda dentada, abriremos las opciones de configuración para que nos sintamos a gusto en nuestro entorno:

  • Mostrar siempre la conversación en pantalla.
  • Mostrar conversación y usuarios.
  • Ver lo que escribe cada usuario con su respectivo color.
  • Mostrar los números de línea (útil si un documento es extenso y queremos mostrar específicamente algo a otros usuarios ).
  • Podemos elegir si queremos escribir de derecha a izquierda (idiomas como el árabe, ver siguiente punto).
  • El menú desplegable para cambiar el idioma, hay muchos, incluido el “español” -castellano en realidad-.
Configurando Etherpad
Configurando Etherpad

Configurando Etherpad para su uso del lado del cliente.

Imaginemos ahora que ya tenemos “montado” nuestro servidor en producción y queremos compartir el enlace al documento que estamos editando, pues hacemos click en el ícono “</>” y copiamos el enlace para enviarlo por correo electrónico, Twitter, etc.

Compartiendo enlaces en Etherpad
Compartiendo enlaces en Etherpad

Visualizando los cambios realizados.

Muy útil poder visualizar los cambios realizados, Etherpad conserva un historial extremadamente detallado, lo notamos mucho cuando se importan documentos al trabajo que estamos realizando (ver el próximo punto). Para ello hacemos click en el ícono de reloj de manecillas y podremos adelantar, atrasar y cada cambio hecho se mostrará en pantalla.

Visualizando cambios en un documento de Etherpad
Visualizando cambios en un documento de Etherpad

Importando documentos.

Esta opción no es muy lógica que digamos pero bueno, muchas veces podemos ahorrar tiempo “copiando y pegando” o, como en este apartado, importando documentos. Las instrucciones dicen que deben ser en formato .html .txt o formato Etherpad pero si instalamos AbiWord podremos “soportar” más formatos de archivo. Para este proceso damos click en las flechas encontradas y “subimos” el documento deseado.

Importando ficheros a un documento Etherpad
Importando ficheros a un documento Etherpad

Guardando documentos.

Con solo hacer click en la estrella de cinco puntas el documento será guardado en la base de datos “dirty.db” para una próxima sesión (recordad que podemos configurar para que trabaje con MySQL). Si queremos llevar nuestro trabajo a otro servidor o simplemente respaldar pues lo que tenemos que hacer es copiar y/o comprimir (con fecha y hora en curso) dicho fichero. Esto es importante si tenemos la necesidad de apagar o reiniciar nuestro servidor (cosa extraña en ambiente GNU/Linux pero sucede). Ah, por cierto, en el ambiente Etherpad cada documentos es denominado “pad“.

Bitácora de registros de eventos en el lado del servidor Etherpad.

Bitácora de registros de eventos en el lado del servidor Etherpad
Bitácora de registros de eventos en el lado del servidor Etherpad

Cada usuario conectado o desconectado, nuevo o ya registrado, lo veremos en la ventana terminal de donde lanzamos nuestro servidor Etherpad. Simplemente mirad y admirad la obra de los programadores de software libre.

Configuraciones avanzadas en Etherpad.

Pues algo que nos sorprendió desde un principio fue que no pedía contraseña para abrir o crear un documento o “pad” como se le denomina por acá. Resulta ser que las configuraciones avanzadas las podemos acceder en la carpeta “/admin”. Volvemos a nuestro ejemplo en red de área local:

http://192.168.1.47:9001/admin

Una vez allí nos pedirá un usuario y contraseña. Pues simplemente para cambiar las credenciales le damos cancelar y finalizamos el proceso que tenemos corriendo en la ventana terminal donde iniciamos el servidor Etherpad. Luego debemos editar el archivo “settings.json“. Acá os mostramos cómo “tumbamos” el servidor y comenzamos a editar el fichero.

Configurando usuarios en Etherpad
Configurando usuarios en Etherpad

Al abrir veremos cantidad de configuraciones y sis nos ponemos a detallar vemos como importantes las opciones para poder trabajar con protocolo SSL (servidores web seguros https) y para conectar con una base de datos MySql (aunque también pueden ser redis, mongodb, casscandra, MariaDB, etc) pero cambiemos las credenciales del administrador y del usuario que vienen por defecto. Buscamos la siguiente sección y cambiamos los valores.

 /* Users for basic authentication. is_admin = true gives access to /admin.
 If you do not uncomment this, /admin will not be available! */
 /*
 "users": {
   "admin": {
     "password": "changeme1",
     "is_admin": true
   },
     "user": {
       "password": "changeme1",
       "is_admin": false
   }
 },
 */

Lo que debemos hacer es descomentar la sección (eliminar “/*” y “*/”) y colocamos los valores que queramos, guardamos y “levantamos” de nuevo el servidor con “run.sh“.

 "users": {
   "admin": {
     "password": "etherpad",
     "is_admin": true
   },
     "user": {
       "password": "etherpad",
       "is_admin": false
   }
 },

Arriba vemos los cambios, si queremos agregar otro usuario que tenga derechos de administrador debemos colocar la variable “is_admin” a “true”. Una vez hayamos reiniciado el servicio Etherpad navegamos a la página de configuración, introducimos nuestro usuario y contraseña y veremos la siguiente pantalla:

Accediendo como administrador a Etherpad
Accediendo como administrador a Etherpad

Al hacer click en “settings” podremos volver a modificar el archivo “settings.json” vía web e incluso podemos “reiniciar” en caliente el servidor Etherpad.

Modificando settings.json via página web
Modificando settings.json via página web

Cambiando usuarios y “plugins”.

Ya en este punto suponemos que estamos lo suficientemente “empapados” de Etherpad por lo tanto ahora os traemos un vídeo donde rápidamente se realiza lo siguiente:

  • Se descarga e instla Etherpad en un sistema oeprativo privativo.
  • Se cambian las contraseñas de los usuarios.
  • Se cambia los “plugins” que queramos (que son bastantes, hay variedad).

¿Qué les pareció la experiencia de aprendizaje?

Fuentes consultadas:

En idioma castellano.

En idioma francés.

Etherpad-Lite instances francophones:

 

En idioma inglés.