Entrega de Arquitectura de Sistemas

mayo 3, 2015 Comments off

Informe del laboratorio 1


Enlace directo

Informe del laboratorio 2


Enlace directo

Informe del laboratorio 3


Enlace directo

Cotización el PC


Presentación de PowerPoint

Categories: General

Instalando Python 2.7 y Django 1.3 en Dreamhost

septiembre 1, 2011 Comments off

Dreamhost es genial para ejecutar sitios web desarrollados con Django. Nos dan acceso SSH que nos permite ejecutar los comandos de manage.py con facilidad; ejecutan Django con Passanger que es más rápido y usa menos memoria que mod_python; y por supuesto: recursos ilimitados, bajos costos y excelente soporte técnico.

Para ejecutar una aplicación Django en Dreamhost solo es necesario configurar el dominio para que utilice Passenger. Es cuestión de editar el dominio y seleccionar la caja que dice “Passenger (Ruby/Python apps only)” y asegurarse que la carpeta pública sea algo como /dominio.com/public/.

El panel de control configura el resto. Sin embargo, la versión de Python y Django que instalan en sus servidores está muy desactualizada (Python 2.4, Django 1.1 por defecto). Por suerte nos permiten compilar programas en el servidor así que instalar una versión moderna es extremadamente fácil.

Este es el proceso que yo utilizo para instalar versiones actualizadas de Python y Django en mis servidores ( sí, plural :P ). Pueden ir copiando y pegando línea por línea en la ventana SSH. Casi podría ser un script automatizado, excepto por que hay que salir y volver a entrar en cierta parte.

Para empezar, hay que conectarse por SSH a su servidor. En Windows pueden usar Putty, en Linux y MacOS ya deberían tener instalado el comando ssh que viene con OpenSSH.

Una vez conectados, vamos a crear una carpeta para descargar los instaladores.

mkdir ~/installers
cd ~/installers

Ahora vamos a descargar, compilar e instalar Python 2.7.2 en unos pocos comandos:

wget http://python.org/ftp/python/2.7.2/Python-2.7.2.tgz
tar -xzvf Python-2.7.2.tgz
cd Python-2.7.2
nice ./configure --prefix=$HOME/local
nice make
nice make install

Ahora tenemos que configurar la shell para que use el nuevo Python 2.7.2 y no la versión desactualizada que estaba instalada.

echo "export PYTHONPATH=\"$HOME/local/lib/python2.7/site-packages\"" >> ~/.bash_profile
echo "export LD_LIBRARY_PATH=\"$HOME/packages/lib\"" >> ~/.bash_profile
echo "export PATH=\"$HOME/local/bin:$PATH\"" >> ~/.bash_profile
logout

Esta es la parte en que tenemos que salir de la sesión y volver a ingresar.

Ahora vamos a comprobar que el nuevo Python quedó instalado. El siguiente comando debería decir algo como /home/<usuario>/local/bin/python

which python

¿Funcionó? Bueno, continuemos.

Nos falta bajar easy_install que luego utilizaremos para actualizar los demás paquetes.

cd ~/installers
wget http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg
sh setuptools-0.6c11-py2.7.egg

Ahora podemos usar el comando easy_install para bajar el resto de utilidades.

easy_install http://pypi.python.org/packages/source/P/Paste/Paste-1.7.5.1.tar.gz
easy_install PIL
easy_install MySQL-python
easy_install Django

La utilidad de Django y MySQL-python debería ser bastante obvia en este punto ¿No?. PIL es un paquete para manipular imágenes (Para crear thumbnails, dibujar y convertir imágenes). Y Paste lo utilizaremos más adelante para depurar problemas en el servidor.

Nos falta configurar Passenger para que utilice nuestro Python. Para esto creamos un archivo passenger_wsgi.py con el siguiente contenido

#!$HOME/local/bin/python
# -*- coding: utf-8 -*-
INTERP = "/home/<usuario>/local/bin/python"
DEBUG = True

import sys
import os
if sys.executable != INTERP: os.execl(INTERP, INTERP, *sys.argv)
sys.path.append(os.getcwd())
os.environ['DJANGO_SETTINGS_MODULE'] = "<proyecto>.settings"
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

if DEBUG:
	from paste.exceptions.errormiddleware import ErrorMiddleware
	application = ErrorMiddleware(application, debug=True)

Recuerden cambiar <usuario> y <proyecto> por el nombre de su usuario y proyecto. Hay una variable DEBUG que permite mostrar en el browser las excepciones que se produzcan. En producción se debería desactivar, pero es muy útil mientras estamos desarrollando. Para esto es que necesitábamos Paste.

Su carpeta $HOME ahora se debería ver así:

installers/
local/
dominio.com/
dominio.com/public/
dominio.com/<proyecto>
dominio.com/passenger_wsgi.py

Con esto ya debería funcionar. Puedes probar en el browser si carga tu aplicación y si hay algún error te debería mostrar la excepción. No olvides desactivar la depuración una vez que pases a producción poniendo DEBUG=False en passenger.py y en settings.py.

Categories: General

FlashPunk para Windows Phone 7

agosto 3, 2011 Comments off

Acabo de publicar mi versión de FlashPunk para Windows Phone 7 (XNA). FlashPunk es un engine para hacer juegos 2D tipo Mario o AngryBirds. Fuentes | Más info.

Splash de FlashPunk en el emulador de Windows Phone 7 (XNA)

El screenshot es el emulador de WP7 corriendo el Splash animado de FlashPunk.

Categories: General Tags: , , ,

Serializar a JSON en Python

junio 3, 2011 Comments off

Un truquillo de esos que ahorran mucho tiempo: Para serializar a JSON sin utilizar librerías externas simplemente es cuestión de crear un diccionario, convertirlo en string y reemplazar comillas simples por comillas dobles:

>>> print unicode({ 'foo': 'hello', 'bar': [4, 8, 15, 16, 23, 42] }).replace("'", '"')
{"foo": "hello", "bar": [4, 8, 15, 16, 23, 42]}

El resultado es un string JSON válido y se puede convertir en un objeto JavaScript con jQuery.parseJSON(str). Este truco maneja perfectamente cadenas unicode o con comillas.

El único problema es al serializar un objeto que pueda contener None (El null de Python) en sus propiedades. En este caso es necesario definir antes el siguiente objeto:

class NullType:
	def __repr__(self):
		return 'null'
null = NullType()

Y al serializar usarlo así:

>>> print unicode({ 'date_of_birth': user.date_of_birth or null }).replace("'", '"')
{"date_of_birth": null}

Funciona muy bien cuando hay que regresar una respuesta rápida por Ajax. Si es algo más complicado les recomiendo usar SimpleJSON que ya viene incluido en Django o para modelos usar la serialización de Django

Categories: General Tags: , , ,

¿Diferencias en los browsers? ¡Blasfemia!

marzo 17, 2011 Comments off

¿Sería mucho pedirle a los señores fabricantes de browsers se pongan de acuerdo al implementar un estándar? Las sombras se ven diferentes en Firefox 4 RC, Chrome 9 e Internet Explorer 9.

Firefox 4, Chrome 9 y IE9 renderizan box-shadow de forma diferente.

Y mientras estamos deseando cosas imposibles… ¿Sería posible que Microsoft implemente el estándar sin BUGS? El IE9 no muestra la sombra si la tabla tiene box-shadow y border-collapse: collapse.

Bueno, será volver al viejo truco de tener una hoja de estilos para todos los browser, una para IE7, otra para IE8 y ahora una más para IE9.

Aquí está el archivo de prueba: box-shadow test

Categories: General

Django Haystack + Xapian en Dreamhost

enero 13, 2011 Comments off

Casi me saco un ojo instalando Xapian en Dreamhost. Lo necesito para usarlo como máquina de búsqueda Haystack en un sitio Django que estoy haciendo (Ya casi les digo cuál, je je).

Haystack es una aplicación Django (un componente) que trae todo listo para hacer un buscador. Solo es cuestión de configurarlo, cambiar unas cuantas plantillas HTML y el buscador queda listo. Y Xapian es la máquina de búsqueda que hace todo el trabajo. Con Haystack tambien se puede usar Solr y Whoosh pero por desempeño me decidí por Xapian.

Me tocó probar muchas versiones y bajar un paquete adicional para poder compilar Xapian. Para documentar el proceso, y por si a alguien le puede servir, aquí están los pasos que tuve que realizar:

NOTA: Yo estoy usando un Python 2.7 que compilé e instalé en el mismo servidor. Todo está en ~/local/ así que si necesitan instalar en otro directorio tendrán que modificar las rutas en los comandos.

Instalar Haystack es fácil. Solo es cuestión de instalar estos dos paquetes:

easy_install http://pypi.python.org/packages/source/d/django-haystack/django-haystack-1.1.0.tar.gz
easy_install http://pypi.python.org/packages/source/x/xapian-haystack/xapian-haystack-1.1.5beta.tar.gz

Esas son las únicas versiones que me funcionaron. Todas las demás combinaciones que probé me dieron errores al crear el índice.

Xapian es más difícil. Primero hay que instalar util-linux-ng y no funciona cualquier versión. La única que no me dio problemas fue la 2.16 (y las probé casi todas):

cd ~/installers
wget ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.16/util-linux-ng-2.16.tar.gz
tar -xzf util-linux-ng-2.16.tar.gz
cd util-linux-ng-2.16
nice ./configure --prefix=$HOME/local
nice make
nice make install

Ignoren los errores de chgrp que salen al hace el make install. Ahora sí, instalemos xapian-core:

cd ~/installers
wget http://oligarchy.co.uk/xapian/1.2.4/xapian-core-1.2.4.tar.gz
tar -xzf xapian-core-1.2.4.tar.gz
cd xapian-core-1.2.4
nice ./configure --prefix=$HOME/local CPPFLAGS="-I$HOME/local/include" LDFLAGS="-L$HOME/local/lib"
nice make
nice make install

CPPFLAGS y LDFLAGS son necesarios para que encuentre las cabeceras y la biblioteca que instalamos con util-linux-ng. Ahora necesitamos xapian-bindings:

cd ~/installers
wget http://oligarchy.co.uk/xapian/1.2.4/xapian-bindings-1.2.4.tar.gz
tar -xzf xapian-bindings-1.2.4.tar.gz
cd xapian-bindings-1.2.4
nice ./configure --prefix=$HOME/local CPPFLAGS="-I$HOME/local/include" LDFLAGS="-L$HOME/local/lib" XAPIAN_CONFIG=$HOME/local/bin/xapian-config --without-php --without-ruby --without-java --without-csharp --without-tcl --with-python
nice make
nice make install

Listo, ahora solo es cuestión de seguir las instrucciones del tutorial de Haystack.

PD: En Windows es mucho más sencillo porque se pueden bajar los binarios pre-compilados aunque dan uno que otro error. No les recomiendo que lo usen para producción pero para desarrollo funciona. Para instalar todo solo hay que ejecutar estos comandos:

easy_install http://pypi.python.org/packages/source/d/django-haystack/django-haystack-1.1.0.tar.gz
easy_install http://pypi.python.org/packages/source/x/xapian-haystack/xapian-haystack-1.1.5beta.tar.gz

Y luego bajar este instalador y correrlo como administrador:

http://www.flax.co.uk/xapian/124/xapian-python-bindings%20for%20Python%202.7.0%20-1.2.4.win32.exe

Para crear el índice manage.py rebuild_index me da un error todo raro pero manage.py update_index funciona sin problemas.

Categories: General Tags: , , , ,

Error 0×80049228 usando autenticación de Windows Live ID

octubre 5, 2010 Comments off

Horas y horas perdidas luchando con ese error.

Estoy tratando de agregar autenticación por Live ID a un sitio que estoy haciendo. La idea es que quien tenga una cuenta de MSN Messenger/Hotmail pueda entrar al sitio sin registrarse.

Al parecer ya funciona pero de vez en cuando me redirige a esta página:

https://consent.live.com/Error.aspx?mkt=en-US&Detail=0×80049228&ru=…

… con un amable mensaje que dice que hay un problema *con mi sitio*.

Lo poquito que he podido averiguar es que alguna cookie de live.com expira y la única forma es cerrar la sesión en live.com y volver a autenticarse.

Lo peor es que ¡le echan la culpa a mi sitio cuando yo no puedo ni mirar las cookies de live.com!

Será ponerlo en el manual: Si les sale error 0×80049228 cierre la sesión en live.com y vuelva a intentar.

Categories: General

Adicionar días hábiles en python

septiembre 1, 2010 Comments off

Una función para sumar o restar días hábiles en Python:

from datetime import date, timedelta

(MON, TUE, WED, THU, FRI, SAT, SUN) = range(7)

def addworkdays(start, days, holidays=(), workdays=(MON,TUE,WED,THU,FRI)):
    weeks, days = divmod(days, len(workdays))
    result = start + timedelta(weeks=weeks)
    lo, hi = min(start, result), max(start, result)
    count = len([h for h in holidays if h >= lo and h <= hi])
    days += count * (-1 if days < 0 else 1)
    for _ in range(days):
        result += timedelta(days=1)
        while result in holidays or result.weekday() not in workdays:
            result += timedelta(days=1)
    return result

Ejemplos:

today = date.today()
print 'hoy:', today             # 2010-09-01
print addworkdays(today, 1)     # 2010-09-02
print addworkdays(today, 3)     # 2010-09-06
print addworkdays(today, 20)    # 2010-09-29

print addworkdays(today, -1)    # 2010-08-31
print addworkdays(today, -3)    # 2010-08-27
print addworkdays(today, -20)	# 2010-08-04

Para especificar los días festivos deben pasar un iterable (un tupple o una lista) con las días que serían días hábiles si no fueran declarados festivos. IMPORTANTE: Solo pasen los festivos que caen entre lunes a viernes. No pasen, por ejemplo, el Domingo de Ramos.

Por ejemplo, los siguientes son los días festivos para Colombia sacados de Wikipedia (Solo los que quedan del 2010 y uno que ya pasó para probar):

holidays2010 = (
    date(2010,  8, 16), date(2010, 10, 18),
    date(2010, 11,  1), date(2010, 11, 15),
    date(2010, 12,  8),
)

print addworkdays(today, 100)               # 2011-01-19
print addworkdays(today, 100, holidays2010) # 2011-01-25

print addworkdays(today, -20)               # 2010-08-04
print addworkdays(today, -20, holidays2010) # 2010-08-05

Licencia: MIT

Formato de moneda en JavaScript

agosto 30, 2010 Comments off

La función quedó un poquito larga pero permite especificar el número de decimales y los separadores (que varían de país a país).

function currency(value, decimals, separators) {
    decimals = decimals >= 0 ? parseInt(decimals, 0) : 2;
    separators = separators || ['.', "'", ','];
    var number = (parseFloat(value) || 0).toFixed(decimals);
    if (number.length <= (4 + decimals))
        return number.replace('.', separators[separators.length - 1]);
    var parts = number.split(/[-.]/);
    value = parts[parts.length > 1 ? parts.length - 2 : 0];
    var result = value.substr(value.length - 3, 3) + (parts.length > 1 ?
        separators[separators.length - 1] + parts[parts.length - 1] : '');
    var start = value.length - 6;
    var idx = 0;
    while (start > -3) {
        result = (start > 0 ? value.substr(start, 3) : value.substr(0, 3 + start))
            + separators[idx] + result;
        idx = (++idx) % 2;
        start -= 3;
    }
    return (parts.length == 3 ? '-' : '') + result;
}

El primer parámetro debe ser un número (cualquier valor inválido regresa “0.00″). Este es el único parámetro obligatorio.

El segundo parámetro es el número de decimales (por defecto 2) y el tercero es un arreglo con los separadores en este orden: Separador de miles, separador de millones, separador de decimales. Por defecto es ['.', "'", ','] que es el que se usa en Colombia.

Algunos ejemplos:

currency(NaN); // "0.00"
currency(0); // "0.00"
currency(123456567.89); // "123'456.567,89"
currency(-123456567.89); // "-123'456.567,89"
currency(1234.56, 1); // "1.234,5"
currency(1234.56, 1, [',', "'", '.']); // "1,234.5"

Licencia: MIT

Sumar/restar fechas con Javascript

mayo 28, 2010 Comments off

No encontré un ejemplo que sirviera pero leyendo la documentación me dí cuenta que se puede utilizar el constructor que acepta milisegundos:

var today = new Date();

// Sumar 7 días.
new Date(today.getTime() + (7 * 24 * 3600 * 1000)),

// Restar 5 días
new Date(today.getTime() - (5 * 24 * 3600 * 1000)),

Tenga en cuenta que esta solución ignora los segundos intercalares. En mi caso no son necesarios pero puede que en el suyo si.